Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
deno
提交
f477b45a
D
deno
项目概览
张重言
/
deno
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
deno
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f477b45a
编写于
11月 06, 2018
作者:
K
Kitson Kelly
提交者:
Ryan Dahl
11月 06, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Improve preparing stack traces
上级
7a17e2ae
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
97 addition
and
97 deletion
+97
-97
js/compiler.ts
js/compiler.ts
+43
-57
js/compiler_test.ts
js/compiler_test.ts
+2
-2
js/main.ts
js/main.ts
+10
-2
js/v8_source_maps.ts
js/v8_source_maps.ts
+42
-36
未找到文件。
js/compiler.ts
浏览文件 @
f477b45a
...
...
@@ -10,7 +10,6 @@ import { window } from "./globals";
import
*
as
os
from
"
./os
"
;
import
{
RawSourceMap
}
from
"
./types
"
;
import
{
assert
,
log
,
notImplemented
}
from
"
./util
"
;
import
*
as
sourceMaps
from
"
./v8_source_maps
"
;
const
EOL
=
"
\n
"
;
const
ASSETS
=
"
$asset$
"
;
...
...
@@ -91,7 +90,7 @@ export class ModuleMetaData implements ts.IScriptSnapshot {
public
readonly
mediaType
:
MediaType
,
public
readonly
sourceCode
:
SourceCode
=
""
,
public
outputCode
:
OutputCode
=
""
,
public
sourceMap
:
SourceMap
=
""
public
sourceMap
:
SourceMap
|
RawSourceMap
=
""
)
{
if
(
outputCode
!==
""
||
fileName
.
endsWith
(
"
.d.ts
"
))
{
this
.
scriptVersion
=
"
1
"
;
...
...
@@ -153,6 +152,8 @@ export class DenoCompiler
>
();
// A reference to global eval, so it can be monkey patched during testing
private
_globalEval
=
globalEval
;
// Keep track of state of the last module requested via `getGeneratedContents`
private
_lastModule
:
ModuleMetaData
|
undefined
;
// A reference to the log utility, so it can be monkey patched during testing
private
_log
=
log
;
// A map of module file names to module meta data
...
...
@@ -376,63 +377,11 @@ export class DenoCompiler
innerMap
.
set
(
moduleSpecifier
,
fileName
);
}
/** Setup being able to map back source references back to their source
*
* TODO is this the best place for this? It is tightly coupled to how the
* compiler works, but it is also tightly coupled to how the whole runtime
* environment is bootstrapped. It also needs efficient access to the
* `outputCode` of the module information, which exists inside of the
* compiler instance.
*/
private
_setupSourceMaps
():
void
{
let
lastModule
:
ModuleMetaData
|
undefined
;
sourceMaps
.
install
({
installPrepareStackTrace
:
true
,
getGeneratedContents
:
(
fileName
:
string
):
string
|
RawSourceMap
=>
{
this
.
_log
(
"
compiler.getGeneratedContents
"
,
fileName
);
if
(
fileName
===
"
gen/bundle/main.js
"
)
{
assert
(
libdeno
.
mainSource
.
length
>
0
);
return
libdeno
.
mainSource
;
}
else
if
(
fileName
===
"
main.js.map
"
)
{
return
libdeno
.
mainSourceMap
;
}
else
if
(
fileName
===
"
deno_main.js
"
)
{
return
""
;
}
else
if
(
!
fileName
.
endsWith
(
"
.map
"
))
{
const
moduleMetaData
=
this
.
_moduleMetaDataMap
.
get
(
fileName
);
if
(
!
moduleMetaData
)
{
lastModule
=
undefined
;
return
""
;
}
lastModule
=
moduleMetaData
;
return
moduleMetaData
.
outputCode
;
}
else
{
if
(
lastModule
&&
lastModule
.
sourceMap
)
{
// Assuming the the map will always be asked for after the source
// code.
const
{
sourceMap
}
=
lastModule
;
lastModule
=
undefined
;
return
sourceMap
;
}
else
{
// Errors thrown here are caught by source-map.
throw
new
Error
(
`Unable to find source map: "
${
fileName
}
"`
);
}
}
}
});
// Pre-compute source maps for main.js.map. This will happen at compile-time
// as long as Compiler is instanciated before the snapshot is created..
const
consumer
=
sourceMaps
.
loadConsumer
(
"
gen/bundle/main.js
"
);
assert
(
consumer
!=
null
);
consumer
!
.
computeColumnSpans
();
}
private
constructor
()
{
if
(
DenoCompiler
.
_instance
)
{
throw
new
TypeError
(
"
Attempt to create an additional compiler.
"
);
}
this
.
_service
=
this
.
_ts
.
createLanguageService
(
this
);
this
.
_setupSourceMaps
();
}
// Deno specific compiler API
...
...
@@ -503,19 +452,55 @@ export class DenoCompiler
moduleMetaData
.
outputCode
=
`
${
outputFile
.
text
}
\n//# sourceURL=
${
fileName
}
`
;
moduleMetaData
.
sourceMap
=
sourceMapFile
.
text
;
moduleMetaData
.
sourceMap
=
JSON
.
parse
(
sourceMapFile
.
text
)
;
}
moduleMetaData
.
scriptVersion
=
"
1
"
;
const
sourceMap
=
moduleMetaData
.
sourceMap
===
"
string
"
?
moduleMetaData
.
sourceMap
:
JSON
.
stringify
(
moduleMetaData
.
sourceMap
);
this
.
_os
.
codeCache
(
fileName
,
sourceCode
,
moduleMetaData
.
outputCode
,
moduleMetaData
.
sourceMap
sourceMap
);
return
moduleMetaData
.
outputCode
;
}
/** Given a fileName, return what was generated by the compiler. */
getGeneratedContents
=
(
fileName
:
string
):
string
|
RawSourceMap
=>
{
this
.
_log
(
"
compiler.getGeneratedContents
"
,
fileName
);
if
(
fileName
===
"
gen/bundle/main.js
"
)
{
assert
(
libdeno
.
mainSource
.
length
>
0
);
return
libdeno
.
mainSource
;
}
else
if
(
fileName
===
"
main.js.map
"
)
{
return
libdeno
.
mainSourceMap
;
}
else
if
(
fileName
===
"
deno_main.js
"
)
{
return
""
;
}
else
if
(
!
fileName
.
endsWith
(
"
.map
"
))
{
const
moduleMetaData
=
this
.
_moduleMetaDataMap
.
get
(
fileName
);
if
(
!
moduleMetaData
)
{
this
.
_lastModule
=
undefined
;
return
""
;
}
this
.
_lastModule
=
moduleMetaData
;
return
moduleMetaData
.
outputCode
;
}
else
{
if
(
this
.
_lastModule
&&
this
.
_lastModule
.
sourceMap
)
{
// Assuming the the map will always be asked for after the source
// code.
const
{
sourceMap
}
=
this
.
_lastModule
;
this
.
_lastModule
=
undefined
;
return
sourceMap
;
}
else
{
// Errors thrown here are caught by source-map.
throw
new
Error
(
`Unable to find source map: "
${
fileName
}
"`
);
}
}
};
/** For a given module specifier and containing file, return a list of
* absolute identifiers for dependent modules that are required by this
* module.
...
...
@@ -586,7 +571,8 @@ export class DenoCompiler
mediaType
=
fetchResponse
.
mediaType
;
sourceCode
=
fetchResponse
.
sourceCode
;
outputCode
=
fetchResponse
.
outputCode
;
sourceMap
=
fetchResponse
.
sourceMap
;
sourceMap
=
fetchResponse
.
sourceMap
&&
JSON
.
parse
(
fetchResponse
.
sourceMap
);
}
assert
(
moduleId
!=
null
,
"
No module ID.
"
);
assert
(
fileName
!=
null
,
"
No file name.
"
);
...
...
js/compiler_test.ts
浏览文件 @
f477b45a
...
...
@@ -438,7 +438,7 @@ test(function compilerRun() {
assert
(
moduleMetaData
.
hasRun
);
assertEqual
(
moduleMetaData
.
sourceCode
,
fooBarTsSource
);
assertEqual
(
moduleMetaData
.
outputCode
,
fooBarTsOutput
);
assertEqual
(
moduleMetaData
.
sourceMap
,
fooBarTsSourcemap
);
assertEqual
(
JSON
.
stringify
(
moduleMetaData
.
sourceMap
)
,
fooBarTsSourcemap
);
assertEqual
(
moduleMetaData
.
exports
,
{
foo
:
"
bar
"
});
assertEqual
(
...
...
@@ -550,7 +550,7 @@ test(function compilerResolveModule() {
);
assertEqual
(
moduleMetaData
.
sourceCode
,
fooBazTsSource
);
assertEqual
(
moduleMetaData
.
outputCode
,
fooBazTsOutput
);
assertEqual
(
moduleMetaData
.
sourceMap
,
fooBazTsSourcemap
);
assertEqual
(
JSON
.
stringify
(
moduleMetaData
.
sourceMap
)
,
fooBazTsSourcemap
);
assert
(
!
moduleMetaData
.
hasRun
);
assert
(
!
moduleMetaData
.
deps
);
assertEqual
(
moduleMetaData
.
exports
,
{});
...
...
js/main.ts
浏览文件 @
f477b45a
...
...
@@ -9,11 +9,19 @@ import { args } from "./deno";
import
{
sendSync
,
handleAsyncMsgFromRust
}
from
"
./dispatch
"
;
import
{
promiseErrorExaminer
,
promiseRejectHandler
}
from
"
./promise_util
"
;
import
{
replLoop
}
from
"
./repl
"
;
import
*
as
sourceMaps
from
"
./v8_source_maps
"
;
import
{
version
}
from
"
typescript
"
;
// Insta
ntiate compiler at the top-level so it decodes source maps for the main
//
bundle during snapshot.
// Insta
ll the source maps handler and do some pre-calculations so all of it is
//
available in the snapshot
const
compiler
=
DenoCompiler
.
instance
();
sourceMaps
.
install
({
installPrepareStackTrace
:
true
,
getGeneratedContents
:
compiler
.
getGeneratedContents
});
const
consumer
=
sourceMaps
.
loadConsumer
(
"
gen/bundle/main.js
"
);
assert
(
consumer
!=
null
);
consumer
!
.
computeColumnSpans
();
function
sendStart
():
msg
.
StartRes
{
const
builder
=
flatbuffers
.
createBuilder
();
...
...
js/v8_source_maps.ts
浏览文件 @
f477b45a
...
...
@@ -3,9 +3,8 @@
// Originated from source-map-support but has been heavily modified for deno.
import
{
SourceMapConsumer
,
MappedPosition
}
from
"
source-map
"
;
import
*
as
base64
from
"
base64-js
"
;
import
{
arrayToStr
}
from
"
./util
"
;
import
{
CallSite
,
RawSourceMap
}
from
"
./types
"
;
import
{
atob
}
from
"
./text_encoding
"
;
const
consumers
=
new
Map
<
string
,
SourceMapConsumer
>
();
...
...
@@ -53,9 +52,9 @@ export function prepareStackTraceWrapper(
// @internal
export
function
prepareStackTrace
(
error
:
Error
,
stack
:
CallSite
[]):
string
{
const
frames
=
stack
.
map
(
(
frame
:
CallSite
)
=>
`\n at
${
wrapCallSite
(
frame
).
toString
()}
`
frame
=>
`\n at
${
wrapCallSite
(
frame
).
toString
()}
`
);
return
error
.
toString
()
+
frames
.
join
(
""
)
;
return
`
${
error
.
toString
()}${
frames
.
join
(
""
)}
`
;
}
// @internal
...
...
@@ -74,11 +73,13 @@ export function wrapCallSite(frame: CallSite): CallSite {
const
column
=
(
frame
.
getColumnNumber
()
||
1
)
-
1
;
const
position
=
mapSourcePosition
({
source
,
line
,
column
});
frame
=
cloneCallSite
(
frame
);
frame
.
getFileName
=
()
=>
position
.
source
;
frame
.
getLineNumber
=
()
=>
position
.
line
;
frame
.
getColumnNumber
=
()
=>
Number
(
position
.
column
)
+
1
;
frame
.
getScriptNameOrSourceURL
=
()
=>
position
.
source
;
frame
.
toString
=
()
=>
CallSiteToString
(
frame
);
Object
.
assign
(
frame
,
{
getFileName
:
()
=>
position
.
source
,
getLineNumber
:
()
=>
position
.
line
,
getColumnNumber
:
()
=>
Number
(
position
.
column
)
+
1
,
getScriptNameOrSourceURL
:
()
=>
position
.
source
,
toString
:
()
=>
CallSiteToString
(
frame
)
});
return
frame
;
}
...
...
@@ -87,8 +88,10 @@ export function wrapCallSite(frame: CallSite): CallSite {
if
(
origin
)
{
origin
=
mapEvalOrigin
(
origin
);
frame
=
cloneCallSite
(
frame
);
frame
.
getEvalOrigin
=
()
=>
origin
;
frame
.
toString
=
()
=>
CallSiteToString
(
frame
);
Object
.
assign
(
frame
,
{
getEvalOrigin
:
()
=>
origin
,
toString
:
()
=>
CallSiteToString
(
frame
)
});
return
frame
;
}
...
...
@@ -96,29 +99,30 @@ export function wrapCallSite(frame: CallSite): CallSite {
return
frame
;
}
function
cloneCallSite
(
frame
:
CallSite
):
CallSite
{
// tslint:disable:no-any
const
obj
:
any
=
{};
const
frame_
=
frame
as
any
;
const
props
=
Object
.
getOwnPropertyNames
(
Object
.
getPrototypeOf
(
frame
));
props
.
forEach
(
name
=>
{
function
cloneCallSite
(
frame
:
CallSite
// mixin: Partial<CallSite> & { toString: () => string }
):
CallSite
{
const
obj
=
{}
as
CallSite
;
const
props
=
Object
.
getOwnPropertyNames
(
Object
.
getPrototypeOf
(
frame
)
)
as
Array
<
keyof
CallSite
>
;
for
(
const
name
of
props
)
{
obj
[
name
]
=
/^
(?:
is|get
)
/
.
test
(
name
)
?
()
=>
frame_
[
name
].
call
(
frame
)
:
frame_
[
name
];
});
return
(
obj
as
any
)
as
CallSite
;
// tslint:enable:no-any
?
()
=>
frame
[
name
].
call
(
frame
)
:
frame
[
name
];
}
return
obj
;
}
// Taken from source-map-support, original copied from V8's messages.js
// MIT License. Copyright (c) 2014 Evan Wallace
function
CallSiteToString
(
frame
:
CallSite
):
string
{
let
fileName
;
let
fileLocation
=
""
;
if
(
frame
.
isNative
())
{
fileLocation
=
"
native
"
;
}
else
{
fileName
=
frame
.
getScriptNameOrSourceURL
();
const
fileName
=
frame
.
getScriptNameOrSourceURL
();
if
(
!
fileName
&&
frame
.
isEval
())
{
fileLocation
=
frame
.
getEvalOrigin
()
||
""
;
fileLocation
+=
"
,
"
;
// Expecting source position to follow.
...
...
@@ -134,10 +138,10 @@ function CallSiteToString(frame: CallSite): string {
}
const
lineNumber
=
frame
.
getLineNumber
();
if
(
lineNumber
!=
null
)
{
fileLocation
+=
"
:
"
+
String
(
lineNumber
)
;
fileLocation
+=
`:
${
lineNumber
}
`
;
const
columnNumber
=
frame
.
getColumnNumber
();
if
(
columnNumber
)
{
fileLocation
+=
"
:
"
+
String
(
columnNumber
)
;
fileLocation
+=
`:
${
columnNumber
}
`
;
}
}
}
...
...
@@ -156,7 +160,7 @@ function CallSiteToString(frame: CallSite): string {
const
methodName
=
frame
.
getMethodName
();
if
(
functionName
)
{
if
(
typeName
&&
functionName
.
indexOf
(
typeName
)
!==
0
)
{
line
+=
typeName
+
"
.
"
;
line
+=
`
${
typeName
}
.`
;
}
line
+=
functionName
;
if
(
...
...
@@ -206,8 +210,7 @@ export function loadConsumer(source: string): SourceMapConsumer | null {
if
(
reSourceMap
.
test
(
sourceMappingURL
))
{
// Support source map URL as a data url
const
rawData
=
sourceMappingURL
.
slice
(
sourceMappingURL
.
indexOf
(
"
,
"
)
+
1
);
const
ui8
=
base64
.
toByteArray
(
rawData
);
sourceMapData
=
arrayToStr
(
ui8
);
sourceMapData
=
atob
(
rawData
);
sourceMappingURL
=
source
;
}
else
{
// TODO Support source map URLs relative to the source URL
...
...
@@ -217,7 +220,7 @@ export function loadConsumer(source: string): SourceMapConsumer | null {
const
rawSourceMap
=
typeof
sourceMapData
===
"
string
"
?
JSON
.
parse
(
sourceMapData
)
?
(
JSON
.
parse
(
sourceMapData
)
as
RawSourceMap
)
:
sourceMapData
;
consumer
=
new
SourceMapConsumer
(
rawSourceMap
);
consumers
.
set
(
source
,
consumer
);
...
...
@@ -225,14 +228,14 @@ export function loadConsumer(source: string): SourceMapConsumer | null {
return
consumer
;
}
// tslint:disable-next-line:max-line-length
const
sourceMapUrlRe
=
/
(?:\/\/[
@#
][
\t]
+sourceMappingURL=
([^\s
'"
]
+
?)[
\t]
*$
)
|
(?:\/\*[
@#
][
\t]
+sourceMappingURL=
([^\*]
+
?)[
\t]
*
(?:\*\/)[
\t]
*$
)
/gm
;
function
retrieveSourceMapURL
(
fileData
:
string
):
string
|
null
{
// Get the URL of the source map
// tslint:disable-next-line:max-line-length
const
re
=
/
(?:\/\/[
@#
][
\t]
+sourceMappingURL=
([^\s
'"
]
+
?)[
\t]
*$
)
|
(?:\/\*[
@#
][
\t]
+sourceMappingURL=
([^\*]
+
?)[
\t]
*
(?:\*\/)[
\t]
*$
)
/gm
;
// Keep executing the search to find the *last* sourceMappingURL to avoid
// picking up sourceMappingURLs from comments, strings, etc.
let
lastMatch
,
match
;
while
((
match
=
r
e
.
exec
(
fileData
)))
{
while
((
match
=
sourceMapUrlR
e
.
exec
(
fileData
)))
{
lastMatch
=
match
;
}
if
(
!
lastMatch
)
{
...
...
@@ -249,11 +252,14 @@ export function mapSourcePosition(position: Position): MappedPosition {
return
consumer
.
originalPositionFor
(
position
);
}
const
stackEvalRe
=
/^eval at
([^
(
]
+
)
\((
.+
)
:
(\d
+
)
:
(\d
+
)\)
$/
;
const
nestedEvalRe
=
/^eval at
([^
(
]
+
)
\((
.+
)\)
$/
;
// Parses code generated by FormatEvalOrigin(), a function inside V8:
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js
function
mapEvalOrigin
(
origin
:
string
):
string
{
// Most eval() calls are in this format
let
match
=
/^eval at
([^
(
]
+
)
\((
.+
)
:
(\d
+
)
:
(\d
+
)\)
$/
.
exec
(
origin
);
let
match
=
stackEvalRe
.
exec
(
origin
);
if
(
match
)
{
const
position
=
mapSourcePosition
({
source
:
match
[
2
],
...
...
@@ -269,7 +275,7 @@ function mapEvalOrigin(origin: string): string {
}
// Parse nested eval() calls using recursion
match
=
/^eval at
([^
(
]
+
)
\((
.+
)\)
$/
.
exec
(
origin
);
match
=
nestedEvalRe
.
exec
(
origin
);
if
(
match
)
{
return
`eval at
${
match
[
1
]}
(
${
mapEvalOrigin
(
match
[
2
])}
)`
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录