mirror of
https://github.com/swc-project/swc.git
synced 2024-12-24 14:16:12 +03:00
Improve swc_ecma_trnasforms (#127)
# swc_ecma_ast - Add PrivateName to Expr # swc_ecma_parser - Fix parsing of private name # swc_ecma_transforms ## Hygiene - It correctly tracks `BindingIdentifer` / `IdentifierReference` - Preserve `IdentiferReference` if it conflicts with a `BindingIdentifier` ## Block scoping - It correctly tracks `BindingIdentifer` / `IdentifierReference` ## Fixer - It removes useless parens. - It removes useless `IdentiferReference`s in comma expressions. ## Classes properties - public prooperty - private property ## Class decorators - implemented
This commit is contained in:
parent
90135ede1e
commit
ba0c7c908c
@ -27,10 +27,10 @@ before_install:
|
||||
|
||||
install:
|
||||
- npm i -g jest
|
||||
- cargo test --no-run --color always --all
|
||||
- cargo test --no-run --color always --all --all-features
|
||||
|
||||
script:
|
||||
- RUST_BACKTRACE=full cargo test --color always --all
|
||||
- RUST_BACKTRACE=full cargo test --color always --all --all-features
|
||||
|
||||
before_deploy:
|
||||
- CARGO_TARGET_DIR=$HOME/cargo-target cargo doc --color always
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
|
||||
cat words.txt | uniq | sort > words_sorted.txt
|
||||
cat words.txt | awk '{$1=$1};1' | uniq | sort > words_sorted.txt
|
||||
mv words_sorted.txt words.txt
|
553
atoms/words.txt
553
atoms/words.txt
@ -1,11 +1,564 @@
|
||||
AbortController
|
||||
AbortSignal
|
||||
AnalyserNode
|
||||
Animation
|
||||
AnimationEffectReadOnly
|
||||
AnimationEffectTiming
|
||||
AnimationEffectTimingReadOnly
|
||||
AnimationEvent
|
||||
AnimationPlaybackEvent
|
||||
AnimationTimeline
|
||||
ApplicationCache
|
||||
ApplicationCacheErrorEvent
|
||||
Array
|
||||
ArrayBuffer
|
||||
Atomics
|
||||
Attr
|
||||
Audio
|
||||
AudioBuffer
|
||||
AudioBufferSourceNode
|
||||
AudioContext
|
||||
AudioDestinationNode
|
||||
AudioListener
|
||||
AudioNode
|
||||
AudioParam
|
||||
AudioProcessingEvent
|
||||
AudioScheduledSourceNode
|
||||
AudioWorkletGlobalScope
|
||||
AudioWorkletNode
|
||||
AudioWorkletProcessor
|
||||
BarProp
|
||||
BaseAudioContext
|
||||
BatteryManager
|
||||
BeforeUnloadEvent
|
||||
BigInt
|
||||
BigInt64Array
|
||||
BigUint64Array
|
||||
BiquadFilterNode
|
||||
Blob
|
||||
BlobEvent
|
||||
Boolean
|
||||
BroadcastChannel
|
||||
BudgetService
|
||||
ByteLengthQueuingStrategy
|
||||
CSS
|
||||
CSSConditionRule
|
||||
CSSFontFaceRule
|
||||
CSSGroupingRule
|
||||
CSSImportRule
|
||||
CSSKeyframeRule
|
||||
CSSKeyframesRule
|
||||
CSSMediaRule
|
||||
CSSNamespaceRule
|
||||
CSSPageRule
|
||||
CSSRule
|
||||
CSSRuleList
|
||||
CSSStyleDeclaration
|
||||
CSSStyleRule
|
||||
CSSStyleSheet
|
||||
CSSSupportsRule
|
||||
Cache
|
||||
CacheStorage
|
||||
CanvasCaptureMediaStreamTrack
|
||||
CanvasGradient
|
||||
CanvasPattern
|
||||
CanvasRenderingContext2D
|
||||
ChannelMergerNode
|
||||
ChannelSplitterNode
|
||||
CharacterData
|
||||
ClipboardEvent
|
||||
CloseEvent
|
||||
Comment
|
||||
CompositionEvent
|
||||
ConstantSourceNode
|
||||
ConvolverNode
|
||||
CountQueuingStrategy
|
||||
Credential
|
||||
CredentialsContainer
|
||||
Crypto
|
||||
CryptoKey
|
||||
CustomElementRegistry
|
||||
CustomEvent
|
||||
DOMError
|
||||
DOMException
|
||||
DOMImplementation
|
||||
DOMMatrix
|
||||
DOMMatrixReadOnly
|
||||
DOMParser
|
||||
DOMPoint
|
||||
DOMPointReadOnly
|
||||
DOMQuad
|
||||
DOMRect
|
||||
DOMRectReadOnly
|
||||
DOMStringList
|
||||
DOMStringMap
|
||||
DOMTokenList
|
||||
DataTransfer
|
||||
DataTransferItem
|
||||
DataTransferItemList
|
||||
DataView
|
||||
Date
|
||||
DelayNode
|
||||
DeviceMotionEvent
|
||||
DeviceOrientationEvent
|
||||
Document
|
||||
DocumentFragment
|
||||
DocumentType
|
||||
DragEvent
|
||||
DynamicsCompressorNode
|
||||
Element
|
||||
Error
|
||||
ErrorEvent
|
||||
EvalError
|
||||
Event
|
||||
EventSource
|
||||
EventTarget
|
||||
File
|
||||
FileList
|
||||
FileReader
|
||||
Float32Array
|
||||
Float64Array
|
||||
FocusEvent
|
||||
FontFace
|
||||
FontFaceSetLoadEvent
|
||||
FormData
|
||||
Function
|
||||
GainNode
|
||||
Gamepad
|
||||
GamepadButton
|
||||
GamepadEvent
|
||||
HTMLAllCollection
|
||||
HTMLAnchorElement
|
||||
HTMLAreaElement
|
||||
HTMLAudioElement
|
||||
HTMLBRElement
|
||||
HTMLBaseElement
|
||||
HTMLBodyElement
|
||||
HTMLButtonElement
|
||||
HTMLCanvasElement
|
||||
HTMLCollection
|
||||
HTMLContentElement
|
||||
HTMLDListElement
|
||||
HTMLDataElement
|
||||
HTMLDataListElement
|
||||
HTMLDetailsElement
|
||||
HTMLDialogElement
|
||||
HTMLDirectoryElement
|
||||
HTMLDivElement
|
||||
HTMLDocument
|
||||
HTMLElement
|
||||
HTMLEmbedElement
|
||||
HTMLFieldSetElement
|
||||
HTMLFontElement
|
||||
HTMLFormControlsCollection
|
||||
HTMLFormElement
|
||||
HTMLFrameElement
|
||||
HTMLFrameSetElement
|
||||
HTMLHRElement
|
||||
HTMLHeadElement
|
||||
HTMLHeadingElement
|
||||
HTMLHtmlElement
|
||||
HTMLIFrameElement
|
||||
HTMLImageElement
|
||||
HTMLInputElement
|
||||
HTMLLIElement
|
||||
HTMLLabelElement
|
||||
HTMLLegendElement
|
||||
HTMLLinkElement
|
||||
HTMLMapElement
|
||||
HTMLMarqueeElement
|
||||
HTMLMediaElement
|
||||
HTMLMenuElement
|
||||
HTMLMetaElement
|
||||
HTMLMeterElement
|
||||
HTMLModElement
|
||||
HTMLOListElement
|
||||
HTMLObjectElement
|
||||
HTMLOptGroupElement
|
||||
HTMLOptionElement
|
||||
HTMLOptionsCollection
|
||||
HTMLOutputElement
|
||||
HTMLParagraphElement
|
||||
HTMLParamElement
|
||||
HTMLPictureElement
|
||||
HTMLPreElement
|
||||
HTMLProgressElement
|
||||
HTMLQuoteElement
|
||||
HTMLScriptElement
|
||||
HTMLSelectElement
|
||||
HTMLShadowElement
|
||||
HTMLSlotElement
|
||||
HTMLSourceElement
|
||||
HTMLSpanElement
|
||||
HTMLStyleElement
|
||||
HTMLTableCaptionElement
|
||||
HTMLTableCellElement
|
||||
HTMLTableColElement
|
||||
HTMLTableElement
|
||||
HTMLTableRowElement
|
||||
HTMLTableSectionElement
|
||||
HTMLTemplateElement
|
||||
HTMLTextAreaElement
|
||||
HTMLTimeElement
|
||||
HTMLTitleElement
|
||||
HTMLTrackElement
|
||||
HTMLUListElement
|
||||
HTMLUnknownElement
|
||||
HTMLVideoElement
|
||||
HashChangeEvent
|
||||
Headers
|
||||
History
|
||||
IDBCursor
|
||||
IDBCursorWithValue
|
||||
IDBDatabase
|
||||
IDBFactory
|
||||
IDBIndex
|
||||
IDBKeyRange
|
||||
IDBObjectStore
|
||||
IDBOpenDBRequest
|
||||
IDBRequest
|
||||
IDBTransaction
|
||||
IDBVersionChangeEvent
|
||||
IIRFilterNode
|
||||
IdleDeadline
|
||||
Image
|
||||
ImageBitmap
|
||||
ImageBitmapRenderingContext
|
||||
ImageCapture
|
||||
ImageData
|
||||
Infinity
|
||||
InputEvent
|
||||
Int16Array
|
||||
Int32Array
|
||||
Int8Array
|
||||
IntersectionObserver
|
||||
IntersectionObserverEntry
|
||||
Intl
|
||||
JSON
|
||||
KeyboardEvent
|
||||
KeyframeEffect
|
||||
KeyframeEffectReadOnly
|
||||
Location
|
||||
MIDIAccess
|
||||
MIDIConnectionEvent
|
||||
MIDIInput
|
||||
MIDIInputMap
|
||||
MIDIMessageEvent
|
||||
MIDIOutput
|
||||
MIDIOutputMap
|
||||
MIDIPort
|
||||
Map
|
||||
Math
|
||||
MediaDeviceInfo
|
||||
MediaDevices
|
||||
MediaElementAudioSourceNode
|
||||
MediaEncryptedEvent
|
||||
MediaError
|
||||
MediaKeyMessageEvent
|
||||
MediaKeySession
|
||||
MediaKeyStatusMap
|
||||
MediaKeySystemAccess
|
||||
MediaList
|
||||
MediaQueryList
|
||||
MediaQueryListEvent
|
||||
MediaRecorder
|
||||
MediaSettingsRange
|
||||
MediaSource
|
||||
MediaStream
|
||||
MediaStreamAudioDestinationNode
|
||||
MediaStreamAudioSourceNode
|
||||
MediaStreamEvent
|
||||
MediaStreamTrack
|
||||
MediaStreamTrackEvent
|
||||
MessageChannel
|
||||
MessageEvent
|
||||
MessagePort
|
||||
MimeType
|
||||
MimeTypeArray
|
||||
MouseEvent
|
||||
MutationEvent
|
||||
MutationObserver
|
||||
MutationRecord
|
||||
NODE_ENV
|
||||
NaN
|
||||
NamedNodeMap
|
||||
NavigationPreloadManager
|
||||
Navigator
|
||||
NetworkInformation
|
||||
Node
|
||||
NodeFilter
|
||||
NodeIterator
|
||||
NodeList
|
||||
Notification
|
||||
Number
|
||||
Object
|
||||
OfflineAudioCompletionEvent
|
||||
OfflineAudioContext
|
||||
OffscreenCanvas
|
||||
Option
|
||||
OscillatorNode
|
||||
PageTransitionEvent
|
||||
PannerNode
|
||||
Path2D
|
||||
PaymentAddress
|
||||
PaymentRequest
|
||||
PaymentRequestUpdateEvent
|
||||
PaymentResponse
|
||||
Performance
|
||||
PerformanceEntry
|
||||
PerformanceLongTaskTiming
|
||||
PerformanceMark
|
||||
PerformanceMeasure
|
||||
PerformanceNavigation
|
||||
PerformanceNavigationTiming
|
||||
PerformanceObserver
|
||||
PerformanceObserverEntryList
|
||||
PerformancePaintTiming
|
||||
PerformanceResourceTiming
|
||||
PerformanceTiming
|
||||
PeriodicWave
|
||||
PermissionStatus
|
||||
Permissions
|
||||
PhotoCapabilities
|
||||
Plugin
|
||||
PluginArray
|
||||
PointerEvent
|
||||
PopStateEvent
|
||||
Presentation
|
||||
PresentationAvailability
|
||||
PresentationConnection
|
||||
PresentationConnectionAvailableEvent
|
||||
PresentationConnectionCloseEvent
|
||||
PresentationConnectionList
|
||||
PresentationReceiver
|
||||
PresentationRequest
|
||||
ProcessingInstruction
|
||||
ProgressEvent
|
||||
Promise
|
||||
PromiseRejectionEvent
|
||||
Proxy
|
||||
PushManager
|
||||
PushSubscription
|
||||
PushSubscriptionOptions
|
||||
RTCCertificate
|
||||
RTCDataChannel
|
||||
RTCDataChannelEvent
|
||||
RTCDtlsTransport
|
||||
RTCIceCandidate
|
||||
RTCIceGatherer
|
||||
RTCIceTransport
|
||||
RTCPeerConnection
|
||||
RTCPeerConnectionIceEvent
|
||||
RTCRtpContributingSource
|
||||
RTCRtpReceiver
|
||||
RTCRtpSender
|
||||
RTCSctpTransport
|
||||
RTCSessionDescription
|
||||
RTCStatsReport
|
||||
RTCTrackEvent
|
||||
RadioNodeList
|
||||
Range
|
||||
RangeError
|
||||
React
|
||||
ReadableStream
|
||||
ReferenceError
|
||||
Reflect
|
||||
RegExp
|
||||
RemotePlayback
|
||||
Request
|
||||
ResizeObserver
|
||||
ResizeObserverEntry
|
||||
Response
|
||||
SVGAElement
|
||||
SVGAngle
|
||||
SVGAnimateElement
|
||||
SVGAnimateMotionElement
|
||||
SVGAnimateTransformElement
|
||||
SVGAnimatedAngle
|
||||
SVGAnimatedBoolean
|
||||
SVGAnimatedEnumeration
|
||||
SVGAnimatedInteger
|
||||
SVGAnimatedLength
|
||||
SVGAnimatedLengthList
|
||||
SVGAnimatedNumber
|
||||
SVGAnimatedNumberList
|
||||
SVGAnimatedPreserveAspectRatio
|
||||
SVGAnimatedRect
|
||||
SVGAnimatedString
|
||||
SVGAnimatedTransformList
|
||||
SVGAnimationElement
|
||||
SVGCircleElement
|
||||
SVGClipPathElement
|
||||
SVGComponentTransferFunctionElement
|
||||
SVGDefsElement
|
||||
SVGDescElement
|
||||
SVGDiscardElement
|
||||
SVGElement
|
||||
SVGEllipseElement
|
||||
SVGFEBlendElement
|
||||
SVGFEColorMatrixElement
|
||||
SVGFEComponentTransferElement
|
||||
SVGFECompositeElement
|
||||
SVGFEConvolveMatrixElement
|
||||
SVGFEDiffuseLightingElement
|
||||
SVGFEDisplacementMapElement
|
||||
SVGFEDistantLightElement
|
||||
SVGFEDropShadowElement
|
||||
SVGFEFloodElement
|
||||
SVGFEFuncAElement
|
||||
SVGFEFuncBElement
|
||||
SVGFEFuncGElement
|
||||
SVGFEFuncRElement
|
||||
SVGFEGaussianBlurElement
|
||||
SVGFEImageElement
|
||||
SVGFEMergeElement
|
||||
SVGFEMergeNodeElement
|
||||
SVGFEMorphologyElement
|
||||
SVGFEOffsetElement
|
||||
SVGFEPointLightElement
|
||||
SVGFESpecularLightingElement
|
||||
SVGFESpotLightElement
|
||||
SVGFETileElement
|
||||
SVGFETurbulenceElement
|
||||
SVGFilterElement
|
||||
SVGForeignObjectElement
|
||||
SVGGElement
|
||||
SVGGeometryElement
|
||||
SVGGradientElement
|
||||
SVGGraphicsElement
|
||||
SVGImageElement
|
||||
SVGLength
|
||||
SVGLengthList
|
||||
SVGLineElement
|
||||
SVGLinearGradientElement
|
||||
SVGMPathElement
|
||||
SVGMarkerElement
|
||||
SVGMaskElement
|
||||
SVGMatrix
|
||||
SVGMetadataElement
|
||||
SVGNumber
|
||||
SVGNumberList
|
||||
SVGPathElement
|
||||
SVGPatternElement
|
||||
SVGPoint
|
||||
SVGPointList
|
||||
SVGPolygonElement
|
||||
SVGPolylineElement
|
||||
SVGPreserveAspectRatio
|
||||
SVGRadialGradientElement
|
||||
SVGRect
|
||||
SVGRectElement
|
||||
SVGSVGElement
|
||||
SVGScriptElement
|
||||
SVGSetElement
|
||||
SVGStopElement
|
||||
SVGStringList
|
||||
SVGStyleElement
|
||||
SVGSwitchElement
|
||||
SVGSymbolElement
|
||||
SVGTSpanElement
|
||||
SVGTextContentElement
|
||||
SVGTextElement
|
||||
SVGTextPathElement
|
||||
SVGTextPositioningElement
|
||||
SVGTitleElement
|
||||
SVGTransform
|
||||
SVGTransformList
|
||||
SVGUnitTypes
|
||||
SVGUseElement
|
||||
SVGViewElement
|
||||
Screen
|
||||
ScreenOrientation
|
||||
ScriptProcessorNode
|
||||
SecurityPolicyViolationEvent
|
||||
Selection
|
||||
ServiceWorker
|
||||
ServiceWorkerContainer
|
||||
ServiceWorkerRegistration
|
||||
Set
|
||||
ShadowRoot
|
||||
SharedArrayBuffer
|
||||
SharedWorker
|
||||
SourceBuffer
|
||||
SourceBufferList
|
||||
SpeechSynthesisEvent
|
||||
SpeechSynthesisUtterance
|
||||
StaticRange
|
||||
StereoPannerNode
|
||||
Storage
|
||||
StorageEvent
|
||||
StorageManager
|
||||
String
|
||||
StyleSheet
|
||||
StyleSheetList
|
||||
SubtleCrypto
|
||||
Symbol
|
||||
SyntaxError
|
||||
TaskAttributionTiming
|
||||
Text
|
||||
TextDecoder
|
||||
TextEncoder
|
||||
TextEvent
|
||||
TextMetrics
|
||||
TextTrack
|
||||
TextTrackCue
|
||||
TextTrackCueList
|
||||
TextTrackList
|
||||
TimeRanges
|
||||
Touch
|
||||
TouchEvent
|
||||
TouchList
|
||||
TrackEvent
|
||||
TransitionEvent
|
||||
TreeWalker
|
||||
TypeError
|
||||
UIEvent
|
||||
URIError
|
||||
URL
|
||||
URLSearchParams
|
||||
Uint16Array
|
||||
Uint32Array
|
||||
Uint8Array
|
||||
Uint8ClampedArray
|
||||
VTTCue
|
||||
ValidityState
|
||||
VisualViewport
|
||||
WaveShaperNode
|
||||
WeakMap
|
||||
WeakSet
|
||||
WebAssembly
|
||||
WebGL2RenderingContext
|
||||
WebGLActiveInfo
|
||||
WebGLBuffer
|
||||
WebGLContextEvent
|
||||
WebGLFramebuffer
|
||||
WebGLProgram
|
||||
WebGLQuery
|
||||
WebGLRenderbuffer
|
||||
WebGLRenderingContext
|
||||
WebGLSampler
|
||||
WebGLShader
|
||||
WebGLShaderPrecisionFormat
|
||||
WebGLSync
|
||||
WebGLTexture
|
||||
WebGLTransformFeedback
|
||||
WebGLUniformLocation
|
||||
WebGLVertexArrayObject
|
||||
WebSocket
|
||||
WheelEvent
|
||||
Window
|
||||
Worker
|
||||
WritableStream
|
||||
XMLDocument
|
||||
XMLHttpRequest
|
||||
XMLHttpRequestEventTarget
|
||||
XMLHttpRequestUpload
|
||||
XMLSerializer
|
||||
XPathEvaluator
|
||||
XPathExpression
|
||||
XPathResult
|
||||
XSLTProcessor
|
||||
_defineProperty
|
||||
_extends
|
||||
_toConsumableArray
|
||||
abstract
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
class::Class,
|
||||
function::Function,
|
||||
ident::Ident,
|
||||
ident::{Ident, PrivateName},
|
||||
jsx::{JSXElement, JSXEmptyExpr, JSXFragment, JSXMemberExpr, JSXNamespacedName},
|
||||
lit::{Lit, Str},
|
||||
operators::{AssignOp, BinaryOp, UnaryOp, UpdateOp},
|
||||
@ -89,6 +89,8 @@ pub enum Expr {
|
||||
TsNonNull(TsNonNullExpr),
|
||||
TsTypeCast(TsTypeCastExpr),
|
||||
TsAs(TsAsExpr),
|
||||
|
||||
PrivateName(PrivateName),
|
||||
}
|
||||
|
||||
#[ast_node]
|
||||
|
@ -375,6 +375,7 @@ impl<'a> Emitter<'a> {
|
||||
Expr::Unary(ref n) => emit!(n),
|
||||
Expr::Update(ref n) => emit!(n),
|
||||
Expr::Yield(ref n) => emit!(n),
|
||||
Expr::PrivateName(ref n) => emit!(n),
|
||||
|
||||
Expr::JSXMebmer(ref n) => emit!(n),
|
||||
Expr::JSXNamespacedName(ref n) => emit!(n),
|
||||
@ -685,6 +686,7 @@ impl<'a> Emitter<'a> {
|
||||
self.wr.increase_indent()?;
|
||||
emit!(expr);
|
||||
self.wr.decrease_indent()?;
|
||||
self.wr.write_line()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1329,13 +1331,15 @@ impl<'a> Emitter<'a> {
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_empty_stmt(&mut self, node: &EmptyStmt) -> Result {
|
||||
punct!(";")
|
||||
punct!(";");
|
||||
self.wr.write_line()?;
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
pub fn emit_debugger_stmt(&mut self, node: &DebuggerStmt) -> Result {
|
||||
keyword!("debugger");
|
||||
semi!();
|
||||
self.wr.write_line()?;
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
|
@ -63,16 +63,18 @@ impl<'a, W: Write> JsWriter<'a, W> {
|
||||
|
||||
if data.len() > 0 {
|
||||
if let Some(span) = span {
|
||||
let loc = self.cm.lookup_char_pos(span.lo());
|
||||
if !span.is_dummy() {
|
||||
let loc = self.cm.lookup_char_pos(span.lo());
|
||||
|
||||
self.srcmap.add(
|
||||
self.line_count as _,
|
||||
self.line_pos as _,
|
||||
loc.line as _,
|
||||
loc.col.0 as _,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
self.srcmap.add(
|
||||
self.line_count as _,
|
||||
self.line_pos as _,
|
||||
loc.line as _,
|
||||
loc.col.0 as _,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if self.line_start {
|
||||
@ -82,16 +84,18 @@ impl<'a, W: Write> JsWriter<'a, W> {
|
||||
cnt += self.raw_write(data.as_bytes())?;
|
||||
|
||||
if let Some(span) = span {
|
||||
let loc = self.cm.lookup_char_pos(span.hi());
|
||||
if !span.is_dummy() {
|
||||
let loc = self.cm.lookup_char_pos(span.hi());
|
||||
|
||||
self.srcmap.add(
|
||||
self.line_count as _,
|
||||
self.line_pos as _,
|
||||
loc.line as _,
|
||||
loc.col.0 as _,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
self.srcmap.add(
|
||||
self.line_count as _,
|
||||
self.line_pos as _,
|
||||
loc.line as _,
|
||||
loc.col.0 as _,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,6 +159,8 @@ impl StartsWithAlphaNum for Expr {
|
||||
| Expr::New(_)
|
||||
| Expr::MetaProp(_) => true,
|
||||
|
||||
Expr::PrivateName(_) => false,
|
||||
|
||||
// Handle other literals.
|
||||
Expr::Lit(_) => false,
|
||||
|
||||
|
@ -1 +1,2 @@
|
||||
(a)=>b;
|
||||
(a)=>b
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(a)=>b;
|
||||
(a)=>b
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(a)=>1;
|
||||
(a)=>1
|
||||
;
|
||||
|
@ -32,7 +32,11 @@
|
||||
};
|
||||
({ a , b , c , d , e })=>{
|
||||
};
|
||||
([a])=>b;
|
||||
([a, b])=>c;
|
||||
({ a })=>b;
|
||||
({ a , b })=>c;
|
||||
([a])=>b
|
||||
;
|
||||
([a, b])=>c
|
||||
;
|
||||
({ a })=>b
|
||||
;
|
||||
({ a , b })=>c
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(eval = 1)=>2;
|
||||
(eval = 1)=>2
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
((a)=>a);
|
||||
((a)=>a
|
||||
);
|
||||
|
@ -1 +1,2 @@
|
||||
(yield)=>1;
|
||||
(yield)=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
()=>a = 1;
|
||||
()=>a = 1
|
||||
;
|
||||
|
@ -1,5 +1,6 @@
|
||||
class a extends b{
|
||||
constructor(){
|
||||
()=>super();
|
||||
()=>super()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -1 +1,2 @@
|
||||
([])=>1;
|
||||
([])=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
([a, ...b])=>1;
|
||||
([a, ...b])=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
({ a })=>1;
|
||||
({ a })=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(a)=>'b';
|
||||
(a)=>'b'
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(eval)=>1;
|
||||
(eval)=>1
|
||||
;
|
||||
|
@ -1 +1,3 @@
|
||||
(a)=>((b, c)=>( a, b, c));
|
||||
(a)=>((b, c)=>( a, b, c)
|
||||
)
|
||||
;
|
||||
|
@ -1,3 +1,4 @@
|
||||
(a)=>({
|
||||
b: 1
|
||||
});
|
||||
})
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(a)=>yield * 1;
|
||||
(a)=>yield * 1
|
||||
;
|
||||
|
@ -1,2 +1,4 @@
|
||||
a = (b)=>false;
|
||||
a = ()=>false;
|
||||
a = (b)=>false
|
||||
;
|
||||
a = ()=>false
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
()=>()=>1;
|
||||
()=>()=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(...a)=>1;
|
||||
(...a)=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(a)=>a * yield;
|
||||
(a)=>a * yield
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
([[[[[[[[[[[[[[[[[[[[{ a =b }]]]]]]]]]]]]]]]]]]]])=>1;
|
||||
([[[[[[[[[[[[[[[[[[[[{ a =b }]]]]]]]]]]]]]]]]]]]])=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(eval)=>'use strict';
|
||||
(eval)=>'use strict'
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
({ a , b =b , a: c , [a]: [d] })=>1;
|
||||
({ a , b =b , a: c , [a]: [d] })=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(eval, a = 1)=>2;
|
||||
(eval, a = 1)=>2
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(a, { b =1 })=>2;
|
||||
(a, { b =1 })=>2
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(yield)=>1;
|
||||
(yield)=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
([a, , b])=>1;
|
||||
([a, , b])=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
()=>'a';
|
||||
()=>'a'
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
({})=>1;
|
||||
({})=>1
|
||||
;
|
||||
|
@ -1,2 +1,3 @@
|
||||
'use strict';
|
||||
(a)=>1;
|
||||
(a)=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
({ a =1 }, {})=>2;
|
||||
({ a =1 }, {})=>2
|
||||
;
|
||||
|
@ -1 +1 @@
|
||||
1.a;
|
||||
1..a;
|
||||
|
@ -1 +1,2 @@
|
||||
(a, b)=>1 + 2;
|
||||
(a, b)=>1 + 2
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
()=>1 + 2;
|
||||
()=>1 + 2
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(arguments)=>1;
|
||||
(arguments)=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(a, b, [c])=>1;
|
||||
(a, b, [c])=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
({ a =1 }, { b =2 }, { c =3 })=>4;
|
||||
({ a =1 }, { b =2 }, { c =3 })=>4
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
({ a =1 })=>a;
|
||||
({ a =1 })=>a
|
||||
;
|
||||
|
@ -1,10 +1,18 @@
|
||||
(a)=>b;
|
||||
(a, b)=>c;
|
||||
()=>b;
|
||||
(a)=>(b)=>c;
|
||||
(a)=>((b)=>c);
|
||||
()=>(b, c)=>d;
|
||||
(a)=>b
|
||||
;
|
||||
(a, b)=>c
|
||||
;
|
||||
()=>b
|
||||
;
|
||||
(a)=>(b)=>c
|
||||
;
|
||||
(a)=>((b)=>c
|
||||
)
|
||||
;
|
||||
()=>(b, c)=>d
|
||||
;
|
||||
(a)=>{
|
||||
return b;
|
||||
};
|
||||
(a)=>'e';
|
||||
(a)=>'e'
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(a)=>'b';
|
||||
(a)=>'b'
|
||||
;
|
||||
|
@ -1 +1 @@
|
||||
1.a;
|
||||
1..a;
|
||||
|
@ -1 +1,2 @@
|
||||
([a])=>[1];
|
||||
([a])=>[1]
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
()=>1, 2;
|
||||
()=>1
|
||||
, 2;
|
||||
|
@ -1,3 +1,4 @@
|
||||
function* a() {
|
||||
()=>yield;
|
||||
()=>yield
|
||||
;
|
||||
}
|
||||
|
@ -1 +1,2 @@
|
||||
(a, b)=>'c';
|
||||
(a, b)=>'c'
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(a)=>(b)=>(c)=>1;
|
||||
(a)=>(b)=>(c)=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(a)=>(b)=>1;
|
||||
(a)=>(b)=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(a, b, ...c)=>1;
|
||||
(a, b, ...c)=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(eval, a)=>1;
|
||||
(eval, a)=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(()=>1);
|
||||
(()=>1
|
||||
);
|
||||
|
@ -1 +1,2 @@
|
||||
(a = 1)=>a * a;
|
||||
(a = 1)=>a * a
|
||||
;
|
||||
|
@ -1,3 +1,4 @@
|
||||
function* a() {
|
||||
(b)=>b * yield;
|
||||
(b)=>b * yield
|
||||
;
|
||||
}
|
||||
|
@ -1 +1,2 @@
|
||||
(a)=>0;
|
||||
(a)=>0
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(a, b, ...c)=>1 + 2;
|
||||
(a, b, ...c)=>1 + 2
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
([a])=>1;
|
||||
([a])=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(a)=>1;
|
||||
(a)=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
()=>1;
|
||||
()=>1
|
||||
;
|
||||
|
@ -1,5 +1,6 @@
|
||||
class a{
|
||||
b() {
|
||||
()=>super.c;
|
||||
()=>super.c
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -1 +1,2 @@
|
||||
([])=>1;
|
||||
([])=>1
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
(()=>null)();
|
||||
(()=>null
|
||||
)();
|
||||
|
@ -1 +1,2 @@
|
||||
([a = 1], [])=>2;
|
||||
([a = 1], [])=>2
|
||||
;
|
||||
|
@ -1 +1,2 @@
|
||||
([a, b])=>1;
|
||||
([a, b])=>1
|
||||
;
|
||||
|
@ -787,7 +787,10 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
// member expression
|
||||
// $obj.name
|
||||
if eat!('.') {
|
||||
let prop: Box<Expr> = Box::new(self.parse_ident_name().map(Expr::from)?);
|
||||
let prop: Box<Expr> = Box::new(self.parse_maybe_private_name().map(|e| match e {
|
||||
Either::Left(p) => Expr::PrivateName(p),
|
||||
Either::Right(i) => Expr::Ident(i),
|
||||
})?);
|
||||
return Ok((
|
||||
Box::new(Expr::Member(MemberExpr {
|
||||
span: span!(start),
|
||||
|
@ -25,7 +25,7 @@ impl<'a, I: Input> Parser<'a, I> {
|
||||
syntax_error!(span!(start), SyntaxError::SpaceBetweenHashAndIdent);
|
||||
}
|
||||
|
||||
let id = self.parse_ident(true, true)?;
|
||||
let id = self.parse_ident_name()?;
|
||||
Ok(PrivateName {
|
||||
span: span!(start),
|
||||
id,
|
||||
|
@ -203,6 +203,9 @@ pub(super) trait ExprExt {
|
||||
|
||||
Expr::Seq(..) => false,
|
||||
|
||||
// MemberExpression is valid assignment target
|
||||
Expr::PrivateName(..) => false,
|
||||
|
||||
// jsx
|
||||
Expr::JSXMebmer(..)
|
||||
| Expr::JSXNamespacedName(..)
|
||||
|
@ -156,6 +156,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: false,
|
||||
@ -220,6 +221,7 @@ Module {
|
||||
),
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: false,
|
||||
|
@ -246,6 +246,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: false,
|
||||
|
@ -71,6 +71,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: false,
|
||||
@ -135,6 +136,7 @@ Module {
|
||||
),
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: true,
|
||||
@ -173,6 +175,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: true,
|
||||
is_optional: false,
|
||||
@ -211,6 +214,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: true,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: false,
|
||||
@ -249,6 +253,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: Some(
|
||||
Public
|
||||
),
|
||||
@ -289,6 +294,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: Some(
|
||||
Protected
|
||||
),
|
||||
@ -329,6 +335,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: Some(
|
||||
Private
|
||||
),
|
||||
@ -369,6 +376,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: true,
|
||||
is_optional: false,
|
||||
@ -407,6 +415,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: true,
|
||||
is_optional: false,
|
||||
@ -445,6 +454,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: true,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: false,
|
||||
@ -483,6 +493,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: Some(
|
||||
Public
|
||||
),
|
||||
@ -523,6 +534,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: Some(
|
||||
Public
|
||||
),
|
||||
@ -563,6 +575,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: true,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: Some(
|
||||
Public
|
||||
),
|
||||
@ -603,6 +616,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: Some(
|
||||
Public
|
||||
),
|
||||
@ -643,6 +657,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: Some(
|
||||
Public
|
||||
),
|
||||
@ -683,6 +698,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: true,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: Some(
|
||||
Public
|
||||
),
|
||||
|
@ -71,6 +71,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: false,
|
||||
@ -109,6 +110,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: true,
|
||||
@ -173,6 +175,7 @@ Module {
|
||||
),
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: false,
|
||||
@ -254,6 +257,7 @@ Module {
|
||||
),
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: false,
|
||||
@ -292,6 +296,7 @@ Module {
|
||||
type_ann: None,
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: false,
|
||||
@ -356,6 +361,7 @@ Module {
|
||||
),
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: false,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: false,
|
||||
|
@ -129,6 +129,7 @@ Module {
|
||||
),
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: true,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: false,
|
||||
@ -225,6 +226,7 @@ Module {
|
||||
),
|
||||
is_static: false,
|
||||
decorators: [],
|
||||
computed: true,
|
||||
accessibility: None,
|
||||
is_abstract: false,
|
||||
is_optional: true,
|
||||
|
@ -1,513 +1,21 @@
|
||||
use crate::scope::{Scope, ScopeKind};
|
||||
use crate::pass::Pass;
|
||||
use ast::*;
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::{Fold, FoldWith, Mark};
|
||||
use swc_common::{Fold, FoldWith};
|
||||
|
||||
pub fn block_scoping() -> BlockFolder<'static> {
|
||||
BlockFolder::new(Mark::fresh(Mark::root()), Scope::new(ScopeKind::Fn, None))
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub struct BlockFolder<'a> {
|
||||
mark: Mark,
|
||||
current: Scope<'a>,
|
||||
}
|
||||
impl<'a> BlockFolder<'a> {
|
||||
fn new(mark: Mark, current: Scope<'a>) -> Self {
|
||||
BlockFolder { mark, current }
|
||||
}
|
||||
|
||||
fn mark_for(&self, sym: &JsWord) -> Option<Mark> {
|
||||
let mut mark = self.mark;
|
||||
let mut scope = Some(&self.current);
|
||||
|
||||
while let Some(cur) = scope {
|
||||
if cur.declared_symbols.contains_key(sym) {
|
||||
return Some(mark);
|
||||
}
|
||||
mark = mark.parent();
|
||||
scope = cur.parent;
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
pub fn block_scoping() -> impl Pass + Clone + Copy {
|
||||
BlockScoping
|
||||
}
|
||||
|
||||
impl<'a> Fold<Function> for BlockFolder<'a> {
|
||||
fn fold(&mut self, f: Function) -> Function {
|
||||
let child_mark = Mark::fresh(self.mark);
|
||||
#[derive(Clone, Copy)]
|
||||
struct BlockScoping;
|
||||
|
||||
let mut child_folder =
|
||||
BlockFolder::new(child_mark, Scope::new(ScopeKind::Fn, Some(&self.current)));
|
||||
|
||||
f.fold_children(&mut child_folder)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<BlockStmt> for BlockFolder<'a> {
|
||||
fn fold(&mut self, block: BlockStmt) -> BlockStmt {
|
||||
let child_mark = Mark::fresh(self.mark);
|
||||
|
||||
let mut child_folder = BlockFolder::new(
|
||||
child_mark,
|
||||
Scope::new(ScopeKind::Block, Some(&self.current)),
|
||||
);
|
||||
|
||||
block.fold_children(&mut child_folder)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<VarDecl> for BlockFolder<'a> {
|
||||
impl Fold<VarDecl> for BlockScoping {
|
||||
fn fold(&mut self, var: VarDecl) -> VarDecl {
|
||||
let var = var.fold_children(self);
|
||||
|
||||
VarDecl {
|
||||
kind: VarDeclKind::Var,
|
||||
..var
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<Pat> for BlockFolder<'a> {
|
||||
fn fold(&mut self, pat: Pat) -> Pat {
|
||||
match pat {
|
||||
Pat::Ident(ident) => {
|
||||
self.current
|
||||
.declared_symbols
|
||||
.insert(ident.sym.clone(), ident.span.ctxt());
|
||||
|
||||
let ident = Ident {
|
||||
span: ident.span.apply_mark(self.mark),
|
||||
sym: ident.sym,
|
||||
..ident
|
||||
};
|
||||
return Pat::Ident(ident);
|
||||
}
|
||||
|
||||
// TODO(kdy1): Is this ok?
|
||||
_ => pat.fold_children(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<Expr> for BlockFolder<'a> {
|
||||
fn fold(&mut self, expr: Expr) -> Expr {
|
||||
match expr {
|
||||
// Leftmost one of a member expression shoukld be resolved.
|
||||
Expr::Member(me) => Expr::Member(MemberExpr {
|
||||
obj: me.obj.fold_with(self),
|
||||
..me
|
||||
}),
|
||||
_ => expr.fold_children(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<VarDeclarator> for BlockFolder<'a> {
|
||||
fn fold(&mut self, decl: VarDeclarator) -> VarDeclarator {
|
||||
VarDeclarator {
|
||||
// order is important
|
||||
init: decl.init.fold_children(self),
|
||||
name: decl.name.fold_with(self),
|
||||
..decl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<Ident> for BlockFolder<'a> {
|
||||
fn fold(&mut self, i: Ident) -> Ident {
|
||||
let Ident { span, sym, .. } = i;
|
||||
if let Some(mark) = self.mark_for(&sym) {
|
||||
Ident {
|
||||
sym,
|
||||
span: span.apply_mark(mark),
|
||||
..i
|
||||
}
|
||||
} else {
|
||||
// Cannot resolve reference. (TODO: Report error)
|
||||
Ident { sym, span, ..i }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use swc_common::SyntaxContext;
|
||||
|
||||
#[test]
|
||||
fn test_mark_for() {
|
||||
::testing::run_test(false, |_, _| {
|
||||
let mark1 = Mark::fresh(Mark::root());
|
||||
let mark2 = Mark::fresh(mark1);
|
||||
let mark3 = Mark::fresh(mark2);
|
||||
let mark4 = Mark::fresh(mark3);
|
||||
|
||||
let folder1 = BlockFolder::new(mark1, Scope::new(ScopeKind::Block, None));
|
||||
let mut folder2 =
|
||||
BlockFolder::new(mark2, Scope::new(ScopeKind::Block, Some(&folder1.current)));
|
||||
folder2
|
||||
.current
|
||||
.declared_symbols
|
||||
.insert("foo".into(), SyntaxContext::empty());
|
||||
|
||||
let mut folder3 =
|
||||
BlockFolder::new(mark3, Scope::new(ScopeKind::Block, Some(&folder2.current)));
|
||||
folder3
|
||||
.current
|
||||
.declared_symbols
|
||||
.insert("bar".into(), SyntaxContext::empty());
|
||||
assert_eq!(folder3.mark_for(&"bar".into()), Some(mark3));
|
||||
|
||||
let mut folder4 =
|
||||
BlockFolder::new(mark4, Scope::new(ScopeKind::Block, Some(&folder3.current)));
|
||||
folder4
|
||||
.current
|
||||
.declared_symbols
|
||||
.insert("foo".into(), SyntaxContext::empty());
|
||||
|
||||
assert_eq!(folder4.mark_for(&"foo".into()), Some(mark4));
|
||||
assert_eq!(folder4.mark_for(&"bar".into()), Some(mark3));
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
block_scoping(),
|
||||
basic,
|
||||
r#"
|
||||
{
|
||||
var foo = 1;
|
||||
{
|
||||
let foo = 2;
|
||||
use(foo);
|
||||
}
|
||||
use(foo)
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
{
|
||||
var foo = 1;
|
||||
{
|
||||
var foo1 = 2;
|
||||
use(foo1);
|
||||
}
|
||||
use(foo);
|
||||
}
|
||||
"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
block_scoping(),
|
||||
general_assignment_patterns,
|
||||
r#"const foo = "foo";
|
||||
|
||||
function foobar() {
|
||||
for (let item of [1, 2, 3]) {
|
||||
let foo = "bar";
|
||||
[bar, foo] = [1, 2];
|
||||
}
|
||||
}"#,
|
||||
r#"var foo = "foo";
|
||||
|
||||
function foobar() {
|
||||
for (var item of [1, 2, 3]) {
|
||||
var foo1 = "bar";
|
||||
[bar, foo1] = [1, 2];
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
block_scoping(),
|
||||
general_function,
|
||||
r#"function test() {
|
||||
let foo = "bar";
|
||||
}"#,
|
||||
r#"function test() {
|
||||
var foo = "bar";
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
ignore,
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
block_scoping(),
|
||||
babel_issue_1051,
|
||||
r#"foo.func1 = function() {
|
||||
if (cond1) {
|
||||
for (;;) {
|
||||
if (cond2) {
|
||||
function func2() {}
|
||||
function func3() {}
|
||||
func4(function() {
|
||||
func2();
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};"#,
|
||||
r#"foo.func1 = function () {
|
||||
if (cond1) {
|
||||
for (;;) {
|
||||
if (cond2) {
|
||||
var _ret = function () {
|
||||
function func2() {}
|
||||
|
||||
function func3() {}
|
||||
|
||||
func4(function () {
|
||||
func2();
|
||||
});
|
||||
return "break";
|
||||
}();
|
||||
|
||||
if (_ret === "break") break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};"#
|
||||
);
|
||||
|
||||
test!(
|
||||
ignore,
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
// TODO(kdy1): WTF is this (again)?
|
||||
block_scoping(),
|
||||
babel_issue_2174,
|
||||
r#"if (true) {
|
||||
function foo() {}
|
||||
function bar() {
|
||||
return foo;
|
||||
}
|
||||
for (var x in {}) {}
|
||||
}"#,
|
||||
r#"
|
||||
if (true) {
|
||||
var foo = function () {};
|
||||
|
||||
var bar = function () {
|
||||
return foo;
|
||||
};
|
||||
|
||||
for (var x in {}) {}
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
ignore,
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
block_scoping(),
|
||||
babel_issue_4363,
|
||||
r#"function WithoutCurlyBraces() {
|
||||
if (true)
|
||||
for (let k in kv) {
|
||||
function foo() { return this }
|
||||
function bar() { return foo.call(this) }
|
||||
console.log(this, k) // => undefined
|
||||
}
|
||||
}
|
||||
|
||||
function WithCurlyBraces() {
|
||||
if (true) {
|
||||
for (let k in kv) {
|
||||
function foo() { return this }
|
||||
function bar() { return foo.call(this) }
|
||||
console.log(this, k) // => 777
|
||||
}
|
||||
}
|
||||
}"#,
|
||||
r#"function WithoutCurlyBraces() {
|
||||
var _this = this;
|
||||
|
||||
if (true) {
|
||||
var _loop = function (k) {
|
||||
function foo() {
|
||||
return this;
|
||||
}
|
||||
|
||||
function bar() {
|
||||
return foo.call(this);
|
||||
}
|
||||
|
||||
console.log(_this, k); // => undefined
|
||||
};
|
||||
|
||||
for (var k in kv) {
|
||||
_loop(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function WithCurlyBraces() {
|
||||
var _this2 = this;
|
||||
|
||||
if (true) {
|
||||
var _loop2 = function (k) {
|
||||
function foo() {
|
||||
return this;
|
||||
}
|
||||
|
||||
function bar() {
|
||||
return foo.call(this);
|
||||
}
|
||||
|
||||
console.log(_this2, k); // => 777
|
||||
};
|
||||
|
||||
for (var k in kv) {
|
||||
_loop2(k);
|
||||
}
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
block_scoping(),
|
||||
babel_issue_4946,
|
||||
r#"(function foo() {
|
||||
let foo = true;
|
||||
});"#,
|
||||
r#"(function foo() {
|
||||
var foo = true;
|
||||
});"#
|
||||
);
|
||||
|
||||
// TODO: try {} catch (a) { let a } should report error
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
block_scoping(),
|
||||
babel_issue_973,
|
||||
r#"let arr = [];
|
||||
for(let i = 0; i < 10; i++) {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
arr.push(() => i);
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"var arr = [];
|
||||
for(var i = 0; i < 10; i++){
|
||||
for(var i1 = 0; i1 < 10; i1++){
|
||||
arr.push(()=>i1);
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
test_exec!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| block_scoping(),
|
||||
pass_assignment,
|
||||
r#"let a = 1;
|
||||
a = 2;
|
||||
expect(a).toBe(2);"#
|
||||
);
|
||||
|
||||
test_exec!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| block_scoping(),
|
||||
pass_call,
|
||||
r#"let a = 1;
|
||||
|
||||
function b() {
|
||||
return a + 1;
|
||||
}
|
||||
|
||||
expect(b()).toBe(2);"#
|
||||
);
|
||||
|
||||
test_exec!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| block_scoping(),
|
||||
pass_update,
|
||||
r#"let a = 1;
|
||||
a++;
|
||||
expect(a).toBe(2);"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
block_scoping(),
|
||||
fn_param,
|
||||
r#"let a = 'foo';
|
||||
function foo(a) {
|
||||
use(a);
|
||||
}"#,
|
||||
r#"var a = 'foo';
|
||||
function foo(a1) {
|
||||
use(a1);
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
block_scoping(),
|
||||
fn_body,
|
||||
r#"let a = 'foo';
|
||||
function foo() {
|
||||
let a = 'bar';
|
||||
use(a);
|
||||
}"#,
|
||||
r#"var a = 'foo';
|
||||
function foo() {
|
||||
var a1 = 'bar';
|
||||
use(a1);
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
block_scoping(),
|
||||
shorthand,
|
||||
r#"let a = 'foo';
|
||||
function foo() {
|
||||
let a = 'bar';
|
||||
use({a});
|
||||
}"#,
|
||||
r#"var a = 'foo';
|
||||
function foo() {
|
||||
var a1 = 'bar';
|
||||
use({a: a1});
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
block_scoping(),
|
||||
same_level,
|
||||
r#"
|
||||
var a = 'foo';
|
||||
var a = 'bar';
|
||||
"#,
|
||||
r#"
|
||||
var a = 'foo';
|
||||
var a = 'bar';
|
||||
"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
block_scoping(),
|
||||
class_block,
|
||||
r#"
|
||||
var Foo = function(_Bar) {
|
||||
_inherits(Foo, _Bar);
|
||||
function Foo() {
|
||||
}
|
||||
return Foo;
|
||||
}(Bar);
|
||||
"#,
|
||||
r#"
|
||||
var Foo = function(_Bar) {
|
||||
_inherits(Foo, _Bar);
|
||||
function Foo() {
|
||||
}
|
||||
return Foo;
|
||||
}(Bar);
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use super::get_prototype_of;
|
||||
use crate::{helpers::Helpers, util::ExprFactory};
|
||||
use ast::*;
|
||||
use std::iter;
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::{Fold, FoldWith, Mark, Visit, VisitWith, DUMMY_SP};
|
||||
|
||||
pub(super) struct SuperCallFinder {
|
||||
@ -236,6 +237,9 @@ macro_rules! ignore_return {
|
||||
ignore_return!(Function);
|
||||
ignore_return!(Class);
|
||||
ignore_return!(ArrowExpr);
|
||||
ignore_return!(Constructor);
|
||||
|
||||
fold_only_key!(ConstructorFolder);
|
||||
|
||||
impl<'a> Fold<Expr> for ConstructorFolder<'a> {
|
||||
fn fold(&mut self, expr: Expr) -> Expr {
|
||||
@ -394,6 +398,12 @@ pub(super) fn replace_this_in_constructor(mark: Mark, c: Constructor) -> (Constr
|
||||
wrap_with_assertiion: bool,
|
||||
}
|
||||
|
||||
impl Fold<Class> for Replacer {
|
||||
fn fold(&mut self, n: Class) -> Class {
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold<Expr> for Replacer {
|
||||
fn fold(&mut self, expr: Expr) -> Expr {
|
||||
match expr {
|
||||
@ -455,3 +465,45 @@ pub(super) fn replace_this_in_constructor(mark: Mark, c: Constructor) -> (Constr
|
||||
|
||||
(c, v.found)
|
||||
}
|
||||
|
||||
/// # In
|
||||
///
|
||||
/// ```js
|
||||
///
|
||||
/// class Example {
|
||||
/// constructor() {
|
||||
/// var Example;
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Out
|
||||
///
|
||||
/// ```js
|
||||
/// var Example = function Example() {
|
||||
/// _classCallCheck(this, Example);
|
||||
/// var Example1;
|
||||
/// };
|
||||
/// ```
|
||||
pub(super) struct VarRenamer<'a> {
|
||||
pub mark: Mark,
|
||||
pub class_name: &'a JsWord,
|
||||
}
|
||||
|
||||
impl<'a> Fold<Pat> for VarRenamer<'a> {
|
||||
fn fold(&mut self, pat: Pat) -> Pat {
|
||||
match pat {
|
||||
Pat::Ident(ident) => {
|
||||
if *self.class_name == ident.sym {
|
||||
return Pat::Ident(Ident {
|
||||
span: ident.span.apply_mark(self.mark),
|
||||
..ident
|
||||
});
|
||||
} else {
|
||||
Pat::Ident(ident)
|
||||
}
|
||||
}
|
||||
_ => pat.fold_children(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
27
ecmascript/transforms/src/compat/es2015/classes/macros.rs
Normal file
27
ecmascript/transforms/src/compat/es2015/classes/macros.rs
Normal file
@ -0,0 +1,27 @@
|
||||
macro_rules! fold_only_key {
|
||||
($T:tt) => {
|
||||
impl<'a> Fold<ClassMember> for $T<'a> {
|
||||
fn fold(&mut self, m: ClassMember) -> ClassMember {
|
||||
match m {
|
||||
ClassMember::Method(m) => ClassMember::Method(Method {
|
||||
key: m.key.fold_with(self),
|
||||
..m
|
||||
}),
|
||||
ClassMember::PrivateMethod(m) => ClassMember::PrivateMethod(PrivateMethod {
|
||||
key: m.key.fold_with(self),
|
||||
..m
|
||||
}),
|
||||
ClassMember::ClassProp(p) => ClassMember::ClassProp(ClassProp {
|
||||
key: p.key.fold_with(self),
|
||||
..p
|
||||
}),
|
||||
ClassMember::PrivateProp(p) => ClassMember::PrivateProp(PrivateProp {
|
||||
key: p.key.fold_with(self),
|
||||
..p
|
||||
}),
|
||||
_ => m,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -1,16 +1,17 @@
|
||||
use self::{
|
||||
constructor::{
|
||||
constructor_fn, make_possible_return_value, replace_this_in_constructor, ConstructorFolder,
|
||||
ReturningMode, SuperCallFinder, SuperFoldingMode,
|
||||
ReturningMode, SuperCallFinder, SuperFoldingMode, VarRenamer,
|
||||
},
|
||||
native::is_native,
|
||||
prop_name::HashKey,
|
||||
super_field::SuperFieldAccessFolder,
|
||||
};
|
||||
use crate::{
|
||||
helpers::Helpers,
|
||||
util::{
|
||||
alias_ident_for, default_constructor, prop_name_to_expr, ExprFactory, ModuleItemLike,
|
||||
StmtLike,
|
||||
alias_ident_for, default_constructor, prepend, prop_name_to_expr, ExprFactory,
|
||||
ModuleItemLike, StmtLike,
|
||||
},
|
||||
};
|
||||
use ast::*;
|
||||
@ -18,7 +19,10 @@ use indexmap::IndexMap;
|
||||
use std::{iter, sync::Arc};
|
||||
use swc_common::{Fold, FoldWith, Mark, Spanned, Visit, VisitWith, DUMMY_SP};
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
mod constructor;
|
||||
mod native;
|
||||
mod prop_name;
|
||||
mod super_field;
|
||||
#[cfg(test)]
|
||||
@ -78,8 +82,6 @@ where
|
||||
match T::try_into_stmt(stmt) {
|
||||
Err(node) => match node.try_into_module_decl() {
|
||||
Ok(decl) => {
|
||||
let decl = decl.fold_children(self);
|
||||
|
||||
match decl {
|
||||
ModuleDecl::ExportDefaultDecl(ExportDefaultDecl::Class(
|
||||
ClassExpr { ident, class },
|
||||
@ -87,6 +89,7 @@ where
|
||||
let ident = ident.unwrap_or_else(|| quote_ident!("_default"));
|
||||
|
||||
let decl = self.fold_class_as_var_decl(ident.clone(), class);
|
||||
let decl = decl.fold_children(self);
|
||||
buf.push(T::from_stmt(Stmt::Decl(Decl::Var(decl))));
|
||||
|
||||
buf.push(
|
||||
@ -112,6 +115,7 @@ where
|
||||
class,
|
||||
})) => {
|
||||
let decl = self.fold_class_as_var_decl(ident, class);
|
||||
let decl = decl.fold_children(self);
|
||||
buf.push(
|
||||
match T::try_from_module_decl(ModuleDecl::ExportDecl(
|
||||
Decl::Var(decl),
|
||||
@ -121,10 +125,12 @@ where
|
||||
},
|
||||
);
|
||||
}
|
||||
_ => buf.push(match T::try_from_module_decl(decl) {
|
||||
Ok(t) => t,
|
||||
Err(..) => unreachable!(),
|
||||
}),
|
||||
_ => {
|
||||
buf.push(match T::try_from_module_decl(decl.fold_children(self)) {
|
||||
Ok(t) => t,
|
||||
Err(..) => unreachable!(),
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
Err(..) => unreachable!(),
|
||||
@ -221,10 +227,7 @@ impl Classes {
|
||||
|
||||
let super_class = class.super_class.clone().unwrap();
|
||||
let is_super_native = match *super_class {
|
||||
Expr::Ident(Ident { ref sym, .. }) => match *sym {
|
||||
js_word!("Object") | js_word!("Array") | js_word!("HTMLElement") => true,
|
||||
_ => false,
|
||||
},
|
||||
Expr::Ident(Ident { ref sym, .. }) => is_native(sym),
|
||||
_ => false,
|
||||
};
|
||||
if is_super_native {
|
||||
@ -318,11 +321,8 @@ impl Classes {
|
||||
|
||||
let mut priv_methods = vec![];
|
||||
let mut methods = vec![];
|
||||
let mut prop_init_stmts = vec![];
|
||||
let mut static_prop_init_stmts = vec![];
|
||||
let mut constructor = None;
|
||||
for member in class.body {
|
||||
let span = member.span();
|
||||
match member {
|
||||
ClassMember::Constructor(c) => {
|
||||
if constructor.is_some() {
|
||||
@ -333,50 +333,16 @@ impl Classes {
|
||||
}
|
||||
ClassMember::PrivateMethod(m) => priv_methods.push(m),
|
||||
ClassMember::Method(m) => methods.push(m),
|
||||
ClassMember::ClassProp(ClassProperty {
|
||||
key,
|
||||
value: Some(right),
|
||||
is_static: true,
|
||||
..
|
||||
}) => static_prop_init_stmts.push(Stmt::Expr(box Expr::Assign(AssignExpr {
|
||||
span,
|
||||
left: PatOrExpr::Expr(box Expr::Member(MemberExpr {
|
||||
span,
|
||||
obj: class_name.clone().as_obj(),
|
||||
computed: match *key {
|
||||
Expr::Ident(..) => false,
|
||||
_ => true,
|
||||
},
|
||||
prop: key,
|
||||
})),
|
||||
op: op!("="),
|
||||
right,
|
||||
}))),
|
||||
ClassMember::ClassProp(ClassProperty {
|
||||
key,
|
||||
value: Some(right),
|
||||
is_static: false,
|
||||
..
|
||||
}) => prop_init_stmts.push(Stmt::Expr(box Expr::Assign(AssignExpr {
|
||||
span,
|
||||
left: PatOrExpr::Expr(box Expr::Member(MemberExpr {
|
||||
span,
|
||||
obj: ThisExpr { span }.as_obj(),
|
||||
computed: match *key {
|
||||
Expr::Ident(..) => false,
|
||||
_ => true,
|
||||
},
|
||||
prop: key,
|
||||
})),
|
||||
op: op!("="),
|
||||
right,
|
||||
}))),
|
||||
|
||||
ClassMember::ClassProp(..) => {
|
||||
unreachable!("classes pass: property\nclass_properties pass should remove this")
|
||||
}
|
||||
ClassMember::PrivateProp(..) => unreachable!(
|
||||
"classes pass: private property\nclass_properties pass should remove this"
|
||||
),
|
||||
ClassMember::TsIndexSignature(s) => {
|
||||
unimplemented!("typescript index signature {:?}", s)
|
||||
}
|
||||
ClassMember::PrivateProp(p) => unimplemented!("private class property {:?}", p),
|
||||
// Skip
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -399,15 +365,24 @@ impl Classes {
|
||||
// Marker for `_this`
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
|
||||
// Process constructor
|
||||
{
|
||||
let mut is_constructor_default = false;
|
||||
let mut constructor = constructor.unwrap_or_else(|| {
|
||||
is_constructor_default = true;
|
||||
let mut c = default_constructor(super_class_ident.is_some());
|
||||
c.params = vec![];
|
||||
c
|
||||
// Process constructor
|
||||
|
||||
let mut constructor =
|
||||
constructor.unwrap_or_else(|| default_constructor(super_class_ident.is_some()));
|
||||
|
||||
// Rename variables to avoid conflicting with class name
|
||||
constructor.body = constructor.body.fold_with(&mut VarRenamer {
|
||||
mark: Mark::fresh(Mark::root()),
|
||||
class_name: &class_name.sym,
|
||||
});
|
||||
|
||||
// Black magic to detect injected constructor.
|
||||
let is_constructor_default = constructor.span.is_dummy();
|
||||
if is_constructor_default {
|
||||
constructor.params = vec![];
|
||||
}
|
||||
|
||||
let mut insert_this = false;
|
||||
|
||||
if super_class_ident.is_some() {
|
||||
@ -439,6 +414,7 @@ impl Classes {
|
||||
if super_class_ident.is_some() {
|
||||
let this = quote_ident!(DUMMY_SP.apply_mark(mark), "_this");
|
||||
|
||||
// We should fold body instead of constructor itself.
|
||||
// Handle `super()`
|
||||
body = body.fold_with(&mut ConstructorFolder {
|
||||
is_constructor_default,
|
||||
@ -502,13 +478,6 @@ impl Classes {
|
||||
if is_this_declared { Some(mark) } else { None },
|
||||
);
|
||||
|
||||
// TODO: Handle
|
||||
//
|
||||
// console.log('foo');
|
||||
// super();
|
||||
// console.log('bar');
|
||||
//
|
||||
//
|
||||
stmts.push(Stmt::Decl(Decl::Fn(FnDecl {
|
||||
ident: class_name.clone(),
|
||||
function: constructor_fn(Constructor {
|
||||
@ -520,9 +489,6 @@ impl Classes {
|
||||
}),
|
||||
declare: false,
|
||||
})));
|
||||
|
||||
// Handle static properties
|
||||
stmts.append(&mut static_prop_init_stmts);
|
||||
}
|
||||
|
||||
// convert class methods
|
||||
@ -561,6 +527,7 @@ impl Classes {
|
||||
is_static: false,
|
||||
folding_constructor: true,
|
||||
in_nested_scope: false,
|
||||
in_injected_define_property_call: false,
|
||||
this_alias_mark: None,
|
||||
};
|
||||
|
||||
@ -575,7 +542,7 @@ impl Classes {
|
||||
kind: VarDeclKind::Var,
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(quote_ident!(DUMMY_SP.apply_mark(mark), "_this2")),
|
||||
name: Pat::Ident(quote_ident!(DUMMY_SP.apply_mark(mark), "_this")),
|
||||
init: Some(box Expr::This(ThisExpr { span: DUMMY_SP })),
|
||||
definite: false,
|
||||
}],
|
||||
@ -704,6 +671,7 @@ impl Classes {
|
||||
is_static: m.is_static,
|
||||
folding_constructor: false,
|
||||
in_nested_scope: false,
|
||||
in_injected_define_property_call: false,
|
||||
this_alias_mark: None,
|
||||
};
|
||||
let mut function = m.function.fold_with(&mut folder);
|
||||
@ -717,7 +685,7 @@ impl Classes {
|
||||
kind: VarDeclKind::Var,
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(quote_ident!(DUMMY_SP.apply_mark(mark), "_this2")),
|
||||
name: Pat::Ident(quote_ident!(DUMMY_SP.apply_mark(mark), "_this")),
|
||||
init: Some(box Expr::This(ThisExpr { span: DUMMY_SP })),
|
||||
definite: false,
|
||||
}],
|
||||
@ -797,19 +765,6 @@ fn get_prototype_of(helpers: &Helpers, obj: &Expr) -> Expr {
|
||||
})
|
||||
}
|
||||
|
||||
/// inject `stmt` after directives
|
||||
fn prepend(stmts: &mut Vec<Stmt>, stmt: Stmt) {
|
||||
let idx = stmts
|
||||
.iter()
|
||||
.position(|item| match item {
|
||||
Stmt::Expr(box Expr::Lit(Lit::Str(..))) => false,
|
||||
_ => true,
|
||||
})
|
||||
.unwrap_or(0);
|
||||
|
||||
stmts.insert(idx, stmt);
|
||||
}
|
||||
|
||||
fn inject_class_call_check(c: &mut Constructor, name: Ident) {
|
||||
let class_call_check = Stmt::Expr(box Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
|
581
ecmascript/transforms/src/compat/es2015/classes/native.rs
Normal file
581
ecmascript/transforms/src/compat/es2015/classes/native.rs
Normal file
@ -0,0 +1,581 @@
|
||||
use swc_atoms::{js_word, JsWord};
|
||||
|
||||
macro_rules! native {
|
||||
(
|
||||
$sym:expr,
|
||||
$(
|
||||
$i:tt
|
||||
),*
|
||||
) => {
|
||||
match $sym{
|
||||
$(
|
||||
js_word!($i) => true,
|
||||
)*
|
||||
_ => false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(super) fn is_native(sym: &JsWord) -> bool {
|
||||
native!(
|
||||
sym,
|
||||
"Array",
|
||||
"ArrayBuffer",
|
||||
"Atomics",
|
||||
"BigInt",
|
||||
"BigInt64Array",
|
||||
"BigUint64Array",
|
||||
"Boolean",
|
||||
"DataView",
|
||||
"Date",
|
||||
"Error",
|
||||
"EvalError",
|
||||
"Float32Array",
|
||||
"Float64Array",
|
||||
"Function",
|
||||
"Infinity",
|
||||
"Int16Array",
|
||||
"Int32Array",
|
||||
"Int8Array",
|
||||
"JSON",
|
||||
"Map",
|
||||
"Math",
|
||||
"NaN",
|
||||
"Number",
|
||||
"Object",
|
||||
"Promise",
|
||||
"Proxy",
|
||||
"RangeError",
|
||||
"ReferenceError",
|
||||
"Reflect",
|
||||
"RegExp",
|
||||
"Set",
|
||||
"SharedArrayBuffer",
|
||||
"String",
|
||||
"Symbol",
|
||||
"SyntaxError",
|
||||
"TypeError",
|
||||
"Uint16Array",
|
||||
"Uint32Array",
|
||||
"Uint8Array",
|
||||
"Uint8ClampedArray",
|
||||
"URIError",
|
||||
"WeakMap",
|
||||
"WeakSet",
|
||||
"AbortController",
|
||||
"AbortSignal",
|
||||
"AnalyserNode",
|
||||
"Animation",
|
||||
"AnimationEffectReadOnly",
|
||||
"AnimationEffectTiming",
|
||||
"AnimationEffectTimingReadOnly",
|
||||
"AnimationEvent",
|
||||
"AnimationPlaybackEvent",
|
||||
"AnimationTimeline",
|
||||
"ApplicationCache",
|
||||
"ApplicationCacheErrorEvent",
|
||||
"Attr",
|
||||
"Audio",
|
||||
"AudioBuffer",
|
||||
"AudioBufferSourceNode",
|
||||
"AudioContext",
|
||||
"AudioDestinationNode",
|
||||
"AudioListener",
|
||||
"AudioNode",
|
||||
"AudioParam",
|
||||
"AudioProcessingEvent",
|
||||
"AudioScheduledSourceNode",
|
||||
"AudioWorkletGlobalScope",
|
||||
"AudioWorkletNode",
|
||||
"AudioWorkletProcessor",
|
||||
"BarProp",
|
||||
"BaseAudioContext",
|
||||
"BatteryManager",
|
||||
"BeforeUnloadEvent",
|
||||
"BiquadFilterNode",
|
||||
"Blob",
|
||||
"BlobEvent",
|
||||
"BroadcastChannel",
|
||||
"BudgetService",
|
||||
"ByteLengthQueuingStrategy",
|
||||
"Cache",
|
||||
"CacheStorage",
|
||||
"CanvasCaptureMediaStreamTrack",
|
||||
"CanvasGradient",
|
||||
"CanvasPattern",
|
||||
"CanvasRenderingContext2D",
|
||||
"ChannelMergerNode",
|
||||
"ChannelSplitterNode",
|
||||
"CharacterData",
|
||||
"ClipboardEvent",
|
||||
"CloseEvent",
|
||||
"Comment",
|
||||
"CompositionEvent",
|
||||
"ConstantSourceNode",
|
||||
"ConvolverNode",
|
||||
"CountQueuingStrategy",
|
||||
"Credential",
|
||||
"CredentialsContainer",
|
||||
"Crypto",
|
||||
"CryptoKey",
|
||||
"CSS",
|
||||
"CSSConditionRule",
|
||||
"CSSFontFaceRule",
|
||||
"CSSGroupingRule",
|
||||
"CSSImportRule",
|
||||
"CSSKeyframeRule",
|
||||
"CSSKeyframesRule",
|
||||
"CSSMediaRule",
|
||||
"CSSNamespaceRule",
|
||||
"CSSPageRule",
|
||||
"CSSRule",
|
||||
"CSSRuleList",
|
||||
"CSSStyleDeclaration",
|
||||
"CSSStyleRule",
|
||||
"CSSStyleSheet",
|
||||
"CSSSupportsRule",
|
||||
"CustomElementRegistry",
|
||||
"CustomEvent",
|
||||
"DataTransfer",
|
||||
"DataTransferItem",
|
||||
"DataTransferItemList",
|
||||
"DelayNode",
|
||||
"DeviceMotionEvent",
|
||||
"DeviceOrientationEvent",
|
||||
"Document",
|
||||
"DocumentFragment",
|
||||
"DocumentType",
|
||||
"DOMError",
|
||||
"DOMException",
|
||||
"DOMImplementation",
|
||||
"DOMMatrix",
|
||||
"DOMMatrixReadOnly",
|
||||
"DOMParser",
|
||||
"DOMPoint",
|
||||
"DOMPointReadOnly",
|
||||
"DOMQuad",
|
||||
"DOMRect",
|
||||
"DOMRectReadOnly",
|
||||
"DOMStringList",
|
||||
"DOMStringMap",
|
||||
"DOMTokenList",
|
||||
"DragEvent",
|
||||
"DynamicsCompressorNode",
|
||||
"Element",
|
||||
"ErrorEvent",
|
||||
"Event",
|
||||
"EventSource",
|
||||
"EventTarget",
|
||||
"File",
|
||||
"FileList",
|
||||
"FileReader",
|
||||
"FocusEvent",
|
||||
"FontFace",
|
||||
"FontFaceSetLoadEvent",
|
||||
"FormData",
|
||||
"GainNode",
|
||||
"Gamepad",
|
||||
"GamepadButton",
|
||||
"GamepadEvent",
|
||||
"HashChangeEvent",
|
||||
"Headers",
|
||||
"History",
|
||||
"HTMLAllCollection",
|
||||
"HTMLAnchorElement",
|
||||
"HTMLAreaElement",
|
||||
"HTMLAudioElement",
|
||||
"HTMLBaseElement",
|
||||
"HTMLBodyElement",
|
||||
"HTMLBRElement",
|
||||
"HTMLButtonElement",
|
||||
"HTMLCanvasElement",
|
||||
"HTMLCollection",
|
||||
"HTMLContentElement",
|
||||
"HTMLDataElement",
|
||||
"HTMLDataListElement",
|
||||
"HTMLDetailsElement",
|
||||
"HTMLDialogElement",
|
||||
"HTMLDirectoryElement",
|
||||
"HTMLDivElement",
|
||||
"HTMLDListElement",
|
||||
"HTMLDocument",
|
||||
"HTMLElement",
|
||||
"HTMLEmbedElement",
|
||||
"HTMLFieldSetElement",
|
||||
"HTMLFontElement",
|
||||
"HTMLFormControlsCollection",
|
||||
"HTMLFormElement",
|
||||
"HTMLFrameElement",
|
||||
"HTMLFrameSetElement",
|
||||
"HTMLHeadElement",
|
||||
"HTMLHeadingElement",
|
||||
"HTMLHRElement",
|
||||
"HTMLHtmlElement",
|
||||
"HTMLIFrameElement",
|
||||
"HTMLImageElement",
|
||||
"HTMLInputElement",
|
||||
"HTMLLabelElement",
|
||||
"HTMLLegendElement",
|
||||
"HTMLLIElement",
|
||||
"HTMLLinkElement",
|
||||
"HTMLMapElement",
|
||||
"HTMLMarqueeElement",
|
||||
"HTMLMediaElement",
|
||||
"HTMLMenuElement",
|
||||
"HTMLMetaElement",
|
||||
"HTMLMeterElement",
|
||||
"HTMLModElement",
|
||||
"HTMLObjectElement",
|
||||
"HTMLOListElement",
|
||||
"HTMLOptGroupElement",
|
||||
"HTMLOptionElement",
|
||||
"HTMLOptionsCollection",
|
||||
"HTMLOutputElement",
|
||||
"HTMLParagraphElement",
|
||||
"HTMLParamElement",
|
||||
"HTMLPictureElement",
|
||||
"HTMLPreElement",
|
||||
"HTMLProgressElement",
|
||||
"HTMLQuoteElement",
|
||||
"HTMLScriptElement",
|
||||
"HTMLSelectElement",
|
||||
"HTMLShadowElement",
|
||||
"HTMLSlotElement",
|
||||
"HTMLSourceElement",
|
||||
"HTMLSpanElement",
|
||||
"HTMLStyleElement",
|
||||
"HTMLTableCaptionElement",
|
||||
"HTMLTableCellElement",
|
||||
"HTMLTableColElement",
|
||||
"HTMLTableElement",
|
||||
"HTMLTableRowElement",
|
||||
"HTMLTableSectionElement",
|
||||
"HTMLTemplateElement",
|
||||
"HTMLTextAreaElement",
|
||||
"HTMLTimeElement",
|
||||
"HTMLTitleElement",
|
||||
"HTMLTrackElement",
|
||||
"HTMLUListElement",
|
||||
"HTMLUnknownElement",
|
||||
"HTMLVideoElement",
|
||||
"IDBCursor",
|
||||
"IDBCursorWithValue",
|
||||
"IDBDatabase",
|
||||
"IDBFactory",
|
||||
"IDBIndex",
|
||||
"IDBKeyRange",
|
||||
"IDBObjectStore",
|
||||
"IDBOpenDBRequest",
|
||||
"IDBRequest",
|
||||
"IDBTransaction",
|
||||
"IDBVersionChangeEvent",
|
||||
"IdleDeadline",
|
||||
"IIRFilterNode",
|
||||
"Image",
|
||||
"ImageBitmap",
|
||||
"ImageBitmapRenderingContext",
|
||||
"ImageCapture",
|
||||
"ImageData",
|
||||
"InputEvent",
|
||||
"IntersectionObserver",
|
||||
"IntersectionObserverEntry",
|
||||
"Intl",
|
||||
"KeyboardEvent",
|
||||
"KeyframeEffect",
|
||||
"KeyframeEffectReadOnly",
|
||||
"Location",
|
||||
"MediaDeviceInfo",
|
||||
"MediaDevices",
|
||||
"MediaElementAudioSourceNode",
|
||||
"MediaEncryptedEvent",
|
||||
"MediaError",
|
||||
"MediaKeyMessageEvent",
|
||||
"MediaKeySession",
|
||||
"MediaKeyStatusMap",
|
||||
"MediaKeySystemAccess",
|
||||
"MediaList",
|
||||
"MediaQueryList",
|
||||
"MediaQueryListEvent",
|
||||
"MediaRecorder",
|
||||
"MediaSettingsRange",
|
||||
"MediaSource",
|
||||
"MediaStream",
|
||||
"MediaStreamAudioDestinationNode",
|
||||
"MediaStreamAudioSourceNode",
|
||||
"MediaStreamEvent",
|
||||
"MediaStreamTrack",
|
||||
"MediaStreamTrackEvent",
|
||||
"MessageChannel",
|
||||
"MessageEvent",
|
||||
"MessagePort",
|
||||
"MIDIAccess",
|
||||
"MIDIConnectionEvent",
|
||||
"MIDIInput",
|
||||
"MIDIInputMap",
|
||||
"MIDIMessageEvent",
|
||||
"MIDIOutput",
|
||||
"MIDIOutputMap",
|
||||
"MIDIPort",
|
||||
"MimeType",
|
||||
"MimeTypeArray",
|
||||
"MouseEvent",
|
||||
"MutationEvent",
|
||||
"MutationObserver",
|
||||
"MutationRecord",
|
||||
"NamedNodeMap",
|
||||
"NavigationPreloadManager",
|
||||
"Navigator",
|
||||
"NetworkInformation",
|
||||
"Node",
|
||||
"NodeFilter",
|
||||
"NodeIterator",
|
||||
"NodeList",
|
||||
"Notification",
|
||||
"OfflineAudioCompletionEvent",
|
||||
"OfflineAudioContext",
|
||||
"OffscreenCanvas",
|
||||
"Option",
|
||||
"OscillatorNode",
|
||||
"PageTransitionEvent",
|
||||
"PannerNode",
|
||||
"Path2D",
|
||||
"PaymentAddress",
|
||||
"PaymentRequest",
|
||||
"PaymentRequestUpdateEvent",
|
||||
"PaymentResponse",
|
||||
"Performance",
|
||||
"PerformanceEntry",
|
||||
"PerformanceLongTaskTiming",
|
||||
"PerformanceMark",
|
||||
"PerformanceMeasure",
|
||||
"PerformanceNavigation",
|
||||
"PerformanceNavigationTiming",
|
||||
"PerformanceObserver",
|
||||
"PerformanceObserverEntryList",
|
||||
"PerformancePaintTiming",
|
||||
"PerformanceResourceTiming",
|
||||
"PerformanceTiming",
|
||||
"PeriodicWave",
|
||||
"Permissions",
|
||||
"PermissionStatus",
|
||||
"PhotoCapabilities",
|
||||
"Plugin",
|
||||
"PluginArray",
|
||||
"PointerEvent",
|
||||
"PopStateEvent",
|
||||
"Presentation",
|
||||
"PresentationAvailability",
|
||||
"PresentationConnection",
|
||||
"PresentationConnectionAvailableEvent",
|
||||
"PresentationConnectionCloseEvent",
|
||||
"PresentationConnectionList",
|
||||
"PresentationReceiver",
|
||||
"PresentationRequest",
|
||||
"ProcessingInstruction",
|
||||
"ProgressEvent",
|
||||
"PromiseRejectionEvent",
|
||||
"PushManager",
|
||||
"PushSubscription",
|
||||
"PushSubscriptionOptions",
|
||||
"RadioNodeList",
|
||||
"Range",
|
||||
"ReadableStream",
|
||||
"RemotePlayback",
|
||||
"Request",
|
||||
"ResizeObserver",
|
||||
"ResizeObserverEntry",
|
||||
"Response",
|
||||
"RTCCertificate",
|
||||
"RTCDataChannel",
|
||||
"RTCDataChannelEvent",
|
||||
"RTCDtlsTransport",
|
||||
"RTCIceCandidate",
|
||||
"RTCIceGatherer",
|
||||
"RTCIceTransport",
|
||||
"RTCPeerConnection",
|
||||
"RTCPeerConnectionIceEvent",
|
||||
"RTCRtpContributingSource",
|
||||
"RTCRtpReceiver",
|
||||
"RTCRtpSender",
|
||||
"RTCSctpTransport",
|
||||
"RTCSessionDescription",
|
||||
"RTCStatsReport",
|
||||
"RTCTrackEvent",
|
||||
"Screen",
|
||||
"ScreenOrientation",
|
||||
"ScriptProcessorNode",
|
||||
"SecurityPolicyViolationEvent",
|
||||
"Selection",
|
||||
"ServiceWorker",
|
||||
"ServiceWorkerContainer",
|
||||
"ServiceWorkerRegistration",
|
||||
"ShadowRoot",
|
||||
"SharedWorker",
|
||||
"SourceBuffer",
|
||||
"SourceBufferList",
|
||||
"SpeechSynthesisEvent",
|
||||
"SpeechSynthesisUtterance",
|
||||
"StaticRange",
|
||||
"StereoPannerNode",
|
||||
"Storage",
|
||||
"StorageEvent",
|
||||
"StorageManager",
|
||||
"StyleSheet",
|
||||
"StyleSheetList",
|
||||
"SubtleCrypto",
|
||||
"SVGAElement",
|
||||
"SVGAngle",
|
||||
"SVGAnimatedAngle",
|
||||
"SVGAnimatedBoolean",
|
||||
"SVGAnimatedEnumeration",
|
||||
"SVGAnimatedInteger",
|
||||
"SVGAnimatedLength",
|
||||
"SVGAnimatedLengthList",
|
||||
"SVGAnimatedNumber",
|
||||
"SVGAnimatedNumberList",
|
||||
"SVGAnimatedPreserveAspectRatio",
|
||||
"SVGAnimatedRect",
|
||||
"SVGAnimatedString",
|
||||
"SVGAnimatedTransformList",
|
||||
"SVGAnimateElement",
|
||||
"SVGAnimateMotionElement",
|
||||
"SVGAnimateTransformElement",
|
||||
"SVGAnimationElement",
|
||||
"SVGCircleElement",
|
||||
"SVGClipPathElement",
|
||||
"SVGComponentTransferFunctionElement",
|
||||
"SVGDefsElement",
|
||||
"SVGDescElement",
|
||||
"SVGDiscardElement",
|
||||
"SVGElement",
|
||||
"SVGEllipseElement",
|
||||
"SVGFEBlendElement",
|
||||
"SVGFEColorMatrixElement",
|
||||
"SVGFEComponentTransferElement",
|
||||
"SVGFECompositeElement",
|
||||
"SVGFEConvolveMatrixElement",
|
||||
"SVGFEDiffuseLightingElement",
|
||||
"SVGFEDisplacementMapElement",
|
||||
"SVGFEDistantLightElement",
|
||||
"SVGFEDropShadowElement",
|
||||
"SVGFEFloodElement",
|
||||
"SVGFEFuncAElement",
|
||||
"SVGFEFuncBElement",
|
||||
"SVGFEFuncGElement",
|
||||
"SVGFEFuncRElement",
|
||||
"SVGFEGaussianBlurElement",
|
||||
"SVGFEImageElement",
|
||||
"SVGFEMergeElement",
|
||||
"SVGFEMergeNodeElement",
|
||||
"SVGFEMorphologyElement",
|
||||
"SVGFEOffsetElement",
|
||||
"SVGFEPointLightElement",
|
||||
"SVGFESpecularLightingElement",
|
||||
"SVGFESpotLightElement",
|
||||
"SVGFETileElement",
|
||||
"SVGFETurbulenceElement",
|
||||
"SVGFilterElement",
|
||||
"SVGForeignObjectElement",
|
||||
"SVGGElement",
|
||||
"SVGGeometryElement",
|
||||
"SVGGradientElement",
|
||||
"SVGGraphicsElement",
|
||||
"SVGImageElement",
|
||||
"SVGLength",
|
||||
"SVGLengthList",
|
||||
"SVGLinearGradientElement",
|
||||
"SVGLineElement",
|
||||
"SVGMarkerElement",
|
||||
"SVGMaskElement",
|
||||
"SVGMatrix",
|
||||
"SVGMetadataElement",
|
||||
"SVGMPathElement",
|
||||
"SVGNumber",
|
||||
"SVGNumberList",
|
||||
"SVGPathElement",
|
||||
"SVGPatternElement",
|
||||
"SVGPoint",
|
||||
"SVGPointList",
|
||||
"SVGPolygonElement",
|
||||
"SVGPolylineElement",
|
||||
"SVGPreserveAspectRatio",
|
||||
"SVGRadialGradientElement",
|
||||
"SVGRect",
|
||||
"SVGRectElement",
|
||||
"SVGScriptElement",
|
||||
"SVGSetElement",
|
||||
"SVGStopElement",
|
||||
"SVGStringList",
|
||||
"SVGStyleElement",
|
||||
"SVGSVGElement",
|
||||
"SVGSwitchElement",
|
||||
"SVGSymbolElement",
|
||||
"SVGTextContentElement",
|
||||
"SVGTextElement",
|
||||
"SVGTextPathElement",
|
||||
"SVGTextPositioningElement",
|
||||
"SVGTitleElement",
|
||||
"SVGTransform",
|
||||
"SVGTransformList",
|
||||
"SVGTSpanElement",
|
||||
"SVGUnitTypes",
|
||||
"SVGUseElement",
|
||||
"SVGViewElement",
|
||||
"TaskAttributionTiming",
|
||||
"Text",
|
||||
"TextDecoder",
|
||||
"TextEncoder",
|
||||
"TextEvent",
|
||||
"TextMetrics",
|
||||
"TextTrack",
|
||||
"TextTrackCue",
|
||||
"TextTrackCueList",
|
||||
"TextTrackList",
|
||||
"TimeRanges",
|
||||
"Touch",
|
||||
"TouchEvent",
|
||||
"TouchList",
|
||||
"TrackEvent",
|
||||
"TransitionEvent",
|
||||
"TreeWalker",
|
||||
"UIEvent",
|
||||
"URL",
|
||||
"URLSearchParams",
|
||||
"ValidityState",
|
||||
"VisualViewport",
|
||||
"VTTCue",
|
||||
"WaveShaperNode",
|
||||
"WebAssembly",
|
||||
"WebGL2RenderingContext",
|
||||
"WebGLActiveInfo",
|
||||
"WebGLBuffer",
|
||||
"WebGLContextEvent",
|
||||
"WebGLFramebuffer",
|
||||
"WebGLProgram",
|
||||
"WebGLQuery",
|
||||
"WebGLRenderbuffer",
|
||||
"WebGLRenderingContext",
|
||||
"WebGLSampler",
|
||||
"WebGLShader",
|
||||
"WebGLShaderPrecisionFormat",
|
||||
"WebGLSync",
|
||||
"WebGLTexture",
|
||||
"WebGLTransformFeedback",
|
||||
"WebGLUniformLocation",
|
||||
"WebGLVertexArrayObject",
|
||||
"WebSocket",
|
||||
"WheelEvent",
|
||||
"Window",
|
||||
"Worker",
|
||||
"WritableStream",
|
||||
"XMLDocument",
|
||||
"XMLHttpRequest",
|
||||
"XMLHttpRequestEventTarget",
|
||||
"XMLHttpRequestUpload",
|
||||
"XMLSerializer",
|
||||
"XPathEvaluator",
|
||||
"XPathExpression",
|
||||
"XPathResult",
|
||||
"XSLTProcessor"
|
||||
)
|
||||
}
|
@ -5,7 +5,7 @@ use crate::{
|
||||
};
|
||||
use ast::*;
|
||||
use std::iter;
|
||||
use swc_common::{Fold, FoldWith, Mark, Span, DUMMY_SP};
|
||||
use swc_common::{Fold, FoldWith, Mark, Span, Spanned, DUMMY_SP};
|
||||
|
||||
/// Process function body.
|
||||
///
|
||||
@ -30,6 +30,9 @@ pub(super) struct SuperFieldAccessFolder<'a> {
|
||||
|
||||
pub folding_constructor: bool,
|
||||
|
||||
/// True while folding **injected** `_defineProperty` call
|
||||
pub in_injected_define_property_call: bool,
|
||||
|
||||
/// True while folding a function / class.
|
||||
pub in_nested_scope: bool,
|
||||
|
||||
@ -59,7 +62,8 @@ macro_rules! mark_nested {
|
||||
($T:tt) => {
|
||||
impl<'a> Fold<$T> for SuperFieldAccessFolder<'a> {
|
||||
fn fold(&mut self, n: $T) -> $T {
|
||||
if self.folding_constructor {
|
||||
// injected `_defineProperty` should be handled like method
|
||||
if self.folding_constructor && !self.in_injected_define_property_call {
|
||||
let old = self.in_nested_scope;
|
||||
self.in_nested_scope = true;
|
||||
let n = n.fold_children(self);
|
||||
@ -76,6 +80,9 @@ macro_rules! mark_nested {
|
||||
mark_nested!(Function);
|
||||
mark_nested!(Class);
|
||||
|
||||
fold_only_key!(SuperFieldAccessFolder);
|
||||
fold_only_key!(SuperCalleeFolder);
|
||||
|
||||
impl<'a> Fold<Expr> for SuperCalleeFolder<'a> {
|
||||
fn fold(&mut self, n: Expr) -> Expr {
|
||||
match n {
|
||||
@ -86,7 +93,7 @@ impl<'a> Fold<Expr> for SuperCalleeFolder<'a> {
|
||||
|
||||
return Expr::Ident(quote_ident!(
|
||||
span.apply_mark(self.this_alias_mark.unwrap()),
|
||||
"_this2"
|
||||
"_this"
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
@ -315,7 +322,7 @@ impl<'a> SuperCalleeFolder<'a> {
|
||||
arg: left,
|
||||
}),
|
||||
}
|
||||
.wrap_with_paren()
|
||||
.into()
|
||||
} else {
|
||||
left
|
||||
};
|
||||
@ -378,6 +385,28 @@ impl<'a> SuperCalleeFolder<'a> {
|
||||
|
||||
impl<'a> Fold<Expr> for SuperFieldAccessFolder<'a> {
|
||||
fn fold(&mut self, n: Expr) -> Expr {
|
||||
// We pretend method folding mode for while folding injected `_defineProperty`
|
||||
// calls.
|
||||
if n.span().is_dummy() {
|
||||
match n {
|
||||
Expr::Call(CallExpr {
|
||||
callee:
|
||||
ExprOrSuper::Expr(box Expr::Ident(Ident {
|
||||
sym: js_word!("_defineProperty"),
|
||||
..
|
||||
})),
|
||||
..
|
||||
}) => {
|
||||
let old = self.in_injected_define_property_call;
|
||||
self.in_injected_define_property_call = true;
|
||||
let n = n.fold_children(self);
|
||||
self.in_injected_define_property_call = old;
|
||||
return n;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let mut callee_folder = SuperCalleeFolder {
|
||||
class_name: self.class_name,
|
||||
inject_get: false,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::*;
|
||||
use crate::compat::es2015::{arrow, block_scoping, Spread};
|
||||
use crate::compat::es2015::{arrow, block_scoping, resolver, Spread};
|
||||
use swc_common::{sync::Lrc, FilePathMapping, SourceMap};
|
||||
use swc_ecma_parser::{EsConfig, Syntax};
|
||||
|
||||
@ -18,16 +18,79 @@ fn tr(helpers: Arc<Helpers>) -> impl Fold<Module> {
|
||||
|
||||
fn spec_tr(helpers: Arc<Helpers>) -> impl Fold<Module> {
|
||||
chain!(
|
||||
resolver(),
|
||||
Classes {
|
||||
helpers: helpers.clone()
|
||||
},
|
||||
Spread {
|
||||
helpers: helpers.clone()
|
||||
},
|
||||
block_scoping()
|
||||
block_scoping(),
|
||||
)
|
||||
}
|
||||
|
||||
test!(
|
||||
syntax(),
|
||||
tr(Default::default()),
|
||||
custom_singleton,
|
||||
r#"
|
||||
let singleton;
|
||||
class Sub extends Foo {
|
||||
constructor() {
|
||||
if (singleton) {
|
||||
return singleton;
|
||||
}
|
||||
singleton = super();
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
let singleton;
|
||||
let Sub = function(_Foo) {
|
||||
_inherits(Sub, _Foo);
|
||||
function Sub() {
|
||||
var _this;
|
||||
_classCallCheck(this, Sub);
|
||||
if (singleton) {
|
||||
return _possibleConstructorReturn(_this, singleton);
|
||||
}
|
||||
singleton = _this = _possibleConstructorReturn(this, _getPrototypeOf(Sub).call(this));
|
||||
return _possibleConstructorReturn(_this);
|
||||
}
|
||||
return Sub;
|
||||
}(Foo);
|
||||
"#
|
||||
);
|
||||
|
||||
test_exec!(
|
||||
syntax(),
|
||||
tr,
|
||||
custom_nested,
|
||||
r#"
|
||||
class Hello{
|
||||
constructor(){
|
||||
return {
|
||||
toString () {
|
||||
return 'hello';
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
class Outer extends Hello{
|
||||
constructor(){
|
||||
var _ref = super();
|
||||
class Inner{
|
||||
constructor(){
|
||||
this[_ref] = 'hello';
|
||||
}
|
||||
}
|
||||
return new Inner();
|
||||
}
|
||||
}
|
||||
expect(new Outer().hello).toBe('hello');
|
||||
"#
|
||||
);
|
||||
|
||||
// spec_constructor_only
|
||||
test!(
|
||||
syntax(),
|
||||
@ -3044,7 +3107,7 @@ function (_super) {
|
||||
}
|
||||
|
||||
return TestEmpty;
|
||||
}((
|
||||
}(
|
||||
/*#__PURE__*/
|
||||
function () {
|
||||
|
||||
@ -3054,7 +3117,7 @@ function () {
|
||||
}
|
||||
|
||||
return _class;
|
||||
}()));
|
||||
}());
|
||||
|
||||
var TestConstructorOnly =
|
||||
/*#__PURE__*/
|
||||
@ -3069,7 +3132,7 @@ function (_super) {
|
||||
}
|
||||
|
||||
return TestConstructorOnly;
|
||||
}((/*#__PURE__*/
|
||||
}(/*#__PURE__*/
|
||||
function () {
|
||||
|
||||
|
||||
@ -3078,7 +3141,7 @@ function () {
|
||||
}
|
||||
|
||||
return _class;
|
||||
}()));
|
||||
}());
|
||||
|
||||
var TestMethodOnly =
|
||||
/*#__PURE__*/
|
||||
@ -3093,7 +3156,7 @@ function (_super) {
|
||||
}
|
||||
|
||||
return TestMethodOnly;
|
||||
}((
|
||||
}(
|
||||
/*#__PURE__*/
|
||||
function () {
|
||||
|
||||
@ -3107,7 +3170,7 @@ function () {
|
||||
value: function method() {}
|
||||
}]);
|
||||
return _class;
|
||||
}()));
|
||||
}());
|
||||
|
||||
var TestConstructorAndMethod =
|
||||
/*#__PURE__*/
|
||||
@ -3122,7 +3185,7 @@ function (_super) {
|
||||
}
|
||||
|
||||
return TestConstructorAndMethod;
|
||||
}((
|
||||
}(
|
||||
/*#__PURE__*/
|
||||
function () {
|
||||
|
||||
@ -3136,7 +3199,7 @@ function () {
|
||||
value: function method() {}
|
||||
}]);
|
||||
return _class;
|
||||
}()));
|
||||
}());
|
||||
|
||||
var TestMultipleMethods =
|
||||
/*#__PURE__*/
|
||||
@ -3151,7 +3214,7 @@ function (_super) {
|
||||
}
|
||||
|
||||
return TestMultipleMethods;
|
||||
}((
|
||||
}(
|
||||
/*#__PURE__*/
|
||||
function () {
|
||||
|
||||
@ -3168,7 +3231,7 @@ function () {
|
||||
value: function m2() {}
|
||||
}]);
|
||||
return _class;
|
||||
}()));
|
||||
}());
|
||||
|
||||
"#);
|
||||
|
||||
@ -3225,9 +3288,9 @@ function (_Hello) {
|
||||
_inherits(Outer, _Hello);
|
||||
|
||||
function Outer() {
|
||||
var _this2 = this;
|
||||
var _this = this;
|
||||
|
||||
var _this;
|
||||
var _this1;
|
||||
|
||||
_classCallCheck(this, Outer);
|
||||
|
||||
@ -3239,7 +3302,7 @@ function (_Hello) {
|
||||
}
|
||||
|
||||
_createClass(Inner, [{
|
||||
key: _this = _possibleConstructorReturn(_this2, _getPrototypeOf(Outer).call(_this2)),
|
||||
key: _this1 = _possibleConstructorReturn(_this, _getPrototypeOf(Outer).call(_this)),
|
||||
value: function () {
|
||||
return 'hello';
|
||||
}
|
||||
@ -3247,7 +3310,7 @@ function (_Hello) {
|
||||
return Inner;
|
||||
}();
|
||||
|
||||
return _possibleConstructorReturn(_this, new Inner());
|
||||
return _possibleConstructorReturn(_this1, new Inner());
|
||||
}
|
||||
|
||||
return Outer;
|
||||
|
@ -118,8 +118,7 @@ impl_for_for_stmt!(ForInStmt);
|
||||
impl_for_for_stmt!(ForOfStmt);
|
||||
|
||||
fn make_ref_ident_for_for_stmt() -> Ident {
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
quote_ident!(DUMMY_SP.apply_mark(mark), "ref")
|
||||
private_ident!("ref")
|
||||
}
|
||||
|
||||
impl Fold<Vec<VarDeclarator>> for Destructuring {
|
||||
@ -338,8 +337,7 @@ impl Fold<Function> for Destructuring {
|
||||
match pat {
|
||||
Pat::Ident(..) => params.push(pat),
|
||||
Pat::Array(..) | Pat::Object(..) | Pat::Assign(..) => {
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
let ref_ident = quote_ident!(span.apply_mark(mark), "ref");
|
||||
let ref_ident = private_ident!(span, "ref");
|
||||
|
||||
params.push(Pat::Ident(ref_ident.clone()));
|
||||
decls.push(VarDeclarator {
|
||||
@ -624,8 +622,7 @@ fn make_ref_ident(decls: &mut Vec<VarDeclarator>, init: Option<Box<Expr>>) -> Id
|
||||
};
|
||||
|
||||
let span = init.span();
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
let ref_ident = quote_ident!(span.apply_mark(mark), s);
|
||||
let ref_ident = private_ident!(span, s);
|
||||
|
||||
decls.push(VarDeclarator {
|
||||
span,
|
||||
@ -678,6 +675,7 @@ fn can_be_null(e: &Expr) -> bool {
|
||||
Expr::Lit(Lit::Null(..))
|
||||
| Expr::This(..)
|
||||
| Expr::Ident(..)
|
||||
| Expr::PrivateName(..)
|
||||
| Expr::Member(..)
|
||||
| Expr::Call(..)
|
||||
| Expr::New(..)
|
||||
|
@ -21,7 +21,7 @@ test!(
|
||||
[{ a = 1 }] = foo"#,
|
||||
r#"let a;
|
||||
var ref, ref1, ref2;
|
||||
( ref = foo, ( ref1 = ref[0], ref2 = ref1.a, a = ref2 === void 0 ? 1 : ref2, ref1), ref);"#
|
||||
ref = foo, ref1 = ref[0], ref2 = ref1.a, a = ref2 === void 0 ? 1 : ref2, ref;"#
|
||||
);
|
||||
|
||||
test!(
|
||||
@ -39,8 +39,8 @@ test!(
|
||||
array2,
|
||||
r#"[a, [b], [c]] = ["hello", [", ", "junk"], ["world"]];"#,
|
||||
r#"var ref, ref1, ref2;
|
||||
( ref = ['hello', [', ', 'junk'], ['world']], a = ref[0],
|
||||
( ref1 = ref[1], b = ref1[0], ref1), ( ref2 = ref[2], c = ref2[0], ref2), ref);
|
||||
ref = ['hello', [', ', 'junk'], ['world']], a = ref[0], ref1 = ref[1],
|
||||
b = ref1[0], ref2 = ref[2], c = ref2[0], ref;
|
||||
"#
|
||||
);
|
||||
|
||||
@ -52,7 +52,7 @@ test!(
|
||||
[x, y] = [1, 2];"#,
|
||||
r#"var x, y;
|
||||
var ref;
|
||||
( ref = [1, 2], x = ref[0], y = ref[1], ref);"#
|
||||
ref = [1, 2], x = ref[0], y = ref[1], ref;"#
|
||||
);
|
||||
|
||||
test!(::swc_ecma_parser::Syntax::default(),
|
||||
@ -301,7 +301,7 @@ test!(
|
||||
babel_issue_5744,
|
||||
r#"if (true) [a, b] = [b, a];"#,
|
||||
r#"var ref;
|
||||
if (true) ( ref = [b, a], a = ref[0], b = ref[1], ref);"#
|
||||
if (true) ref = [b, a], a = ref[0], b = ref[1], ref;"#
|
||||
);
|
||||
|
||||
test!(
|
||||
@ -337,7 +337,7 @@ test!(
|
||||
member_expr,
|
||||
r#"[foo.foo, foo.bar] = [1, 2];"#,
|
||||
r#"var ref;
|
||||
( ref = [1, 2], foo.foo = ref[0], foo.bar = ref[1], ref);"#
|
||||
ref = [1, 2], foo.foo = ref[0], foo.bar = ref[1], ref;"#
|
||||
);
|
||||
|
||||
test!(
|
||||
|
@ -189,43 +189,41 @@ impl Actual {
|
||||
test: Some(box Expr::Unary(UnaryExpr {
|
||||
span: DUMMY_SP,
|
||||
op: op!("!"),
|
||||
arg: box Expr::Paren(ParenExpr {
|
||||
span: DUMMY_SP,
|
||||
expr: box Expr::Member(MemberExpr {
|
||||
arg: {
|
||||
let step_expr = box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
obj: ExprOrSuper::Expr(box Expr::Assign(AssignExpr {
|
||||
left: PatOrExpr::Pat(box Pat::Ident(step.clone())),
|
||||
op: op!("="),
|
||||
// `_iterator.next()`
|
||||
right: box Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(box Pat::Ident(normal_completion_ident.clone())),
|
||||
op: op!("="),
|
||||
right: box Expr::Paren(ParenExpr {
|
||||
// `_iterator.next`
|
||||
callee: MemberExpr {
|
||||
span: DUMMY_SP,
|
||||
expr: box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(box Pat::Ident(step.clone())),
|
||||
op: op!("="),
|
||||
// `_iterator.next()`
|
||||
right: box Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
// `_iterator.next`
|
||||
callee: MemberExpr {
|
||||
span: DUMMY_SP,
|
||||
computed: false,
|
||||
obj: ExprOrSuper::Expr(box Expr::Ident(
|
||||
iterator.clone(),
|
||||
)),
|
||||
prop: member_expr!(DUMMY_SP, next),
|
||||
}
|
||||
.as_callee(),
|
||||
args: vec![],
|
||||
type_args: Default::default(),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})),
|
||||
computed: false,
|
||||
prop: box Expr::Ident(quote_ident!("done")),
|
||||
}),
|
||||
}),
|
||||
computed: false,
|
||||
obj: ExprOrSuper::Expr(box Expr::Ident(iterator.clone())),
|
||||
prop: member_expr!(DUMMY_SP, next),
|
||||
}
|
||||
.as_callee(),
|
||||
args: vec![],
|
||||
type_args: Default::default(),
|
||||
}),
|
||||
});
|
||||
|
||||
let iteration_normal_completion = box Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(box Pat::Ident(normal_completion_ident.clone())),
|
||||
op: op!("="),
|
||||
right: box Expr::Member(MemberExpr {
|
||||
span: DUMMY_SP,
|
||||
obj: step_expr.as_obj(),
|
||||
computed: false,
|
||||
prop: box Expr::Ident(quote_ident!("done")),
|
||||
}),
|
||||
});
|
||||
|
||||
iteration_normal_completion
|
||||
},
|
||||
})),
|
||||
|
||||
// `_iteratorNormalCompletion = true`
|
||||
|
@ -12,12 +12,14 @@ mod tests;
|
||||
/// var number = function (x) {
|
||||
/// return x;
|
||||
/// };
|
||||
/// var Foo = (class {});
|
||||
/// ```
|
||||
/// ## Out
|
||||
/// ```js
|
||||
/// var number = function number(x) {
|
||||
/// return x;
|
||||
/// }
|
||||
/// var Foo = (class Foo {});
|
||||
/// ```
|
||||
pub fn function_name() -> FnName {
|
||||
FnName
|
||||
@ -32,11 +34,14 @@ struct Renamer {
|
||||
|
||||
impl Fold<VarDeclarator> for FnName {
|
||||
fn fold(&mut self, decl: VarDeclarator) -> VarDeclarator {
|
||||
let mut decl = decl.fold_children(self);
|
||||
|
||||
match decl.name {
|
||||
Pat::Ident(ref ident) => {
|
||||
let init = decl.init.fold_with(&mut Renamer {
|
||||
Pat::Ident(ref mut ident) => {
|
||||
let mut folder = Renamer {
|
||||
name: Some(ident.clone()),
|
||||
});
|
||||
};
|
||||
let init = decl.init.fold_with(&mut folder);
|
||||
|
||||
return VarDeclarator { init, ..decl };
|
||||
}
|
||||
@ -47,18 +52,20 @@ impl Fold<VarDeclarator> for FnName {
|
||||
|
||||
impl Fold<AssignExpr> for FnName {
|
||||
fn fold(&mut self, expr: AssignExpr) -> AssignExpr {
|
||||
let expr = expr.fold_children(self);
|
||||
let mut expr = expr.fold_children(self);
|
||||
|
||||
if expr.op != op!("=") {
|
||||
return expr;
|
||||
}
|
||||
|
||||
match expr.left {
|
||||
PatOrExpr::Pat(box Pat::Ident(ref ident))
|
||||
| PatOrExpr::Expr(box Expr::Ident(ref ident)) => {
|
||||
let right = expr.right.fold_with(&mut Renamer {
|
||||
PatOrExpr::Pat(box Pat::Ident(ref mut ident))
|
||||
| PatOrExpr::Expr(box Expr::Ident(ref mut ident)) => {
|
||||
let mut folder = Renamer {
|
||||
name: Some(ident.clone()),
|
||||
});
|
||||
};
|
||||
|
||||
let right = expr.right.fold_with(&mut folder);
|
||||
|
||||
return AssignExpr { right, ..expr };
|
||||
}
|
||||
@ -67,27 +74,36 @@ impl Fold<AssignExpr> for FnName {
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold<FnExpr> for Renamer {
|
||||
fn fold(&mut self, expr: FnExpr) -> FnExpr {
|
||||
match expr.ident {
|
||||
Some(..) => return expr,
|
||||
None => FnExpr {
|
||||
ident: self.name.take(),
|
||||
..expr
|
||||
},
|
||||
macro_rules! impl_for {
|
||||
($T:tt) => {
|
||||
impl Fold<$T> for Renamer {
|
||||
fn fold(&mut self, node: $T) -> $T {
|
||||
match node.ident {
|
||||
Some(..) => return node,
|
||||
None => $T {
|
||||
ident: self.name.take(),
|
||||
..node
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
impl_for!(FnExpr);
|
||||
impl_for!(ClassExpr);
|
||||
|
||||
macro_rules! noop {
|
||||
($T:tt) => {
|
||||
impl Fold<$T> for Renamer {
|
||||
/// Don't recurse.
|
||||
fn fold(&mut self, node: $T) -> $T {
|
||||
node
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl Fold<ObjectLit> for Renamer {
|
||||
/// Don't recurse.
|
||||
fn fold(&mut self, node: ObjectLit) -> ObjectLit {
|
||||
node
|
||||
}
|
||||
}
|
||||
impl Fold<ArrayLit> for Renamer {
|
||||
/// Don't recurse.
|
||||
fn fold(&mut self, node: ArrayLit) -> ArrayLit {
|
||||
node
|
||||
}
|
||||
}
|
||||
noop!(ObjectLit);
|
||||
noop!(ArrayLit);
|
||||
noop!(CallExpr);
|
||||
noop!(NewExpr);
|
||||
|
@ -1,8 +1,17 @@
|
||||
use super::*;
|
||||
use crate::{
|
||||
compat::es2015::{block_scoping, resolver},
|
||||
helpers::Helpers,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
fn tr(_helpers: Arc<Helpers>) -> impl Fold<Module> {
|
||||
chain!(resolver(), function_name(), block_scoping())
|
||||
}
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
FnName,
|
||||
tr(Default::default()),
|
||||
basic,
|
||||
r#"var number = function (x) {
|
||||
return x;
|
||||
@ -14,7 +23,7 @@ test!(
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
FnName,
|
||||
tr(Default::default()),
|
||||
assign,
|
||||
r#"number = function (x) {
|
||||
return x;
|
||||
@ -26,7 +35,7 @@ test!(
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
FnName,
|
||||
tr(Default::default()),
|
||||
let_complex,
|
||||
r#"
|
||||
let TestClass = {
|
||||
@ -41,7 +50,7 @@ let TestClass = {
|
||||
};
|
||||
"#,
|
||||
r#"
|
||||
let TestClass = {
|
||||
var TestClass = {
|
||||
name: "John Doe",
|
||||
|
||||
testMethodFailure() {
|
||||
@ -53,3 +62,33 @@ let TestClass = {
|
||||
}
|
||||
"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(Default::default()),
|
||||
class_simple,
|
||||
r#"
|
||||
var Foo = function() {
|
||||
var Foo = function () {
|
||||
_classCallCheck(this, Foo);
|
||||
};
|
||||
_defineProperty(Foo, 'num', 0);
|
||||
return Foo;
|
||||
}();
|
||||
expect(Foo.num).toBe(0);
|
||||
expect(Foo.num = 1).toBe(1);
|
||||
expect(Foo.name).toBe('Foo');
|
||||
"#,
|
||||
r#"
|
||||
var Foo = function() {
|
||||
var Foo = function Foo() {
|
||||
_classCallCheck(this, Foo);
|
||||
};
|
||||
_defineProperty(Foo, 'num', 0);
|
||||
return Foo;
|
||||
}();
|
||||
expect(Foo.num).toBe(0);
|
||||
expect(Foo.num = 1).toBe(1);
|
||||
expect(Foo.name).toBe('Foo');
|
||||
"#
|
||||
);
|
||||
|
@ -2,8 +2,9 @@ pub use self::{
|
||||
arrow::arrow, block_scoped_fn::BlockScopedFns, block_scoping::block_scoping, classes::Classes,
|
||||
computed_props::computed_properties, destructuring::destructuring,
|
||||
duplicate_keys::duplicate_keys, for_of::for_of, function_name::function_name,
|
||||
instanceof::InstanceOf, parameters::parameters, shorthand_property::Shorthand, spread::Spread,
|
||||
sticky_regex::StickyRegex, template_literal::TemplateLiteral, typeof_symbol::TypeOfSymbol,
|
||||
instanceof::InstanceOf, parameters::parameters, resolver::resolver,
|
||||
shorthand_property::Shorthand, spread::Spread, sticky_regex::StickyRegex,
|
||||
template_literal::TemplateLiteral, typeof_symbol::TypeOfSymbol,
|
||||
};
|
||||
use crate::{helpers::Helpers, pass::Pass};
|
||||
use ast::{Expr, Module, Stmt};
|
||||
@ -20,6 +21,7 @@ mod for_of;
|
||||
mod function_name;
|
||||
mod instanceof;
|
||||
mod parameters;
|
||||
mod resolver;
|
||||
mod shorthand_property;
|
||||
mod spread;
|
||||
mod sticky_regex;
|
||||
@ -53,18 +55,19 @@ pub fn es2015(helpers: &Arc<Helpers>) -> impl Pass + Clone {
|
||||
fn stmts(helpers: &Arc<Helpers>) -> impl Pass + Clone {
|
||||
chain_at!(
|
||||
Stmt,
|
||||
function_name(),
|
||||
exprs(helpers),
|
||||
Classes {
|
||||
helpers: helpers.clone(),
|
||||
},
|
||||
BlockScopedFns,
|
||||
function_name(),
|
||||
parameters(),
|
||||
)
|
||||
}
|
||||
|
||||
chain_at!(
|
||||
Module,
|
||||
resolver(),
|
||||
stmts(helpers),
|
||||
for_of(),
|
||||
computed_properties(helpers.clone()),
|
||||
|
@ -26,8 +26,7 @@ impl Params {
|
||||
match param {
|
||||
Pat::Ident(..) => params.push(param),
|
||||
Pat::Array(..) | Pat::Object(..) => {
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
let binding = quote_ident!(span.apply_mark(mark), "param");
|
||||
let binding = private_ident!(span, "param");
|
||||
|
||||
params.push(Pat::Ident(binding.clone()));
|
||||
decls.push(VarDeclarator {
|
||||
@ -38,8 +37,7 @@ impl Params {
|
||||
})
|
||||
}
|
||||
Pat::Assign(..) => {
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
let binding = quote_ident!(span.apply_mark(mark), "param");
|
||||
let binding = private_ident!(span, "param");
|
||||
|
||||
params.push(Pat::Ident(binding.clone()));
|
||||
// This expands to invalid code, but is fixed by destructing pass
|
||||
|
@ -4,9 +4,10 @@ use std::sync::Arc;
|
||||
|
||||
fn tr(helpers: Arc<Helpers>) -> impl Fold<Module> {
|
||||
chain!(
|
||||
crate::compat::es2015::resolver(),
|
||||
Params,
|
||||
crate::compat::es2015::destructuring(helpers.clone()),
|
||||
crate::compat::es2015::block_scoping()
|
||||
crate::compat::es2015::block_scoping(),
|
||||
)
|
||||
}
|
||||
|
||||
|
336
ecmascript/transforms/src/compat/es2015/resolver/mod.rs
Normal file
336
ecmascript/transforms/src/compat/es2015/resolver/mod.rs
Normal file
@ -0,0 +1,336 @@
|
||||
use crate::scope::ScopeKind;
|
||||
use ast::*;
|
||||
use fnv::FnvHashSet;
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::{Fold, FoldWith, Mark, SyntaxContext};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
const LOG: bool = true;
|
||||
|
||||
pub fn resolver() -> Resolver<'static> {
|
||||
Resolver::new(
|
||||
Mark::fresh(Mark::root()),
|
||||
Scope::new(ScopeKind::Fn, None),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Scope<'a> {
|
||||
/// Parent scope of this scope
|
||||
parent: Option<&'a Scope<'a>>,
|
||||
|
||||
/// Kind of the scope.
|
||||
kind: ScopeKind,
|
||||
|
||||
/// All references declared in this scope
|
||||
declared_symbols: FnvHashSet<JsWord>,
|
||||
}
|
||||
|
||||
impl<'a> Scope<'a> {
|
||||
pub fn new(kind: ScopeKind, parent: Option<&'a Scope<'a>>) -> Self {
|
||||
Scope {
|
||||
parent,
|
||||
kind,
|
||||
declared_symbols: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Resolver<'a> {
|
||||
mark: Mark,
|
||||
current: Scope<'a>,
|
||||
cur_defining: Option<(JsWord, Mark)>,
|
||||
in_var_decl: bool,
|
||||
}
|
||||
|
||||
impl<'a> Resolver<'a> {
|
||||
fn new(mark: Mark, current: Scope<'a>, cur_defining: Option<(JsWord, Mark)>) -> Self {
|
||||
Resolver {
|
||||
mark,
|
||||
current,
|
||||
cur_defining,
|
||||
in_var_decl: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_for(&self, sym: &JsWord) -> Option<Mark> {
|
||||
let mut mark = self.mark;
|
||||
let mut scope = Some(&self.current);
|
||||
|
||||
while let Some(cur) = scope {
|
||||
if cur.declared_symbols.contains(sym) {
|
||||
if mark == Mark::root() {
|
||||
return None;
|
||||
}
|
||||
return Some(mark);
|
||||
}
|
||||
mark = mark.parent();
|
||||
scope = cur.parent;
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn fold_binding_ident(&mut self, ident: Ident) -> Ident {
|
||||
if cfg!(debug_assertions) && LOG {
|
||||
eprintln!("resolver: Binding {}{:?}", ident.sym, ident.span.ctxt());
|
||||
}
|
||||
|
||||
if ident.span.ctxt() != SyntaxContext::empty() {
|
||||
return ident;
|
||||
}
|
||||
|
||||
let (should_insert, mark) = if let Some((ref cur, override_mark)) = self.cur_defining {
|
||||
if *cur != ident.sym {
|
||||
(true, self.mark)
|
||||
} else {
|
||||
(false, override_mark)
|
||||
}
|
||||
} else {
|
||||
(true, self.mark)
|
||||
};
|
||||
|
||||
if should_insert {
|
||||
self.current.declared_symbols.insert(ident.sym.clone());
|
||||
}
|
||||
|
||||
Ident {
|
||||
span: if mark == Mark::root() {
|
||||
ident.span
|
||||
} else {
|
||||
eprintln!("\t-> {:?}", mark);
|
||||
ident.span.apply_mark(mark)
|
||||
},
|
||||
sym: ident.sym,
|
||||
..ident
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<Function> for Resolver<'a> {
|
||||
fn fold(&mut self, mut f: Function) -> Function {
|
||||
let child_mark = Mark::fresh(self.mark);
|
||||
|
||||
// Child folder
|
||||
let mut folder = Resolver::new(
|
||||
child_mark,
|
||||
Scope::new(ScopeKind::Fn, Some(&self.current)),
|
||||
self.cur_defining.take(),
|
||||
);
|
||||
|
||||
folder.in_var_decl = true;
|
||||
f.params = f.params.fold_with(&mut folder);
|
||||
|
||||
folder.in_var_decl = false;
|
||||
f.body = f.body.map(|stmt| stmt.fold_children(&mut folder));
|
||||
|
||||
self.cur_defining = folder.cur_defining;
|
||||
|
||||
f
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<BlockStmt> for Resolver<'a> {
|
||||
fn fold(&mut self, block: BlockStmt) -> BlockStmt {
|
||||
let child_mark = Mark::fresh(self.mark);
|
||||
|
||||
let mut child_folder = Resolver::new(
|
||||
child_mark,
|
||||
Scope::new(ScopeKind::Block, Some(&self.current)),
|
||||
self.cur_defining.take(),
|
||||
);
|
||||
|
||||
let block = block.fold_children(&mut child_folder);
|
||||
self.cur_defining = child_folder.cur_defining;
|
||||
block
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<FnExpr> for Resolver<'a> {
|
||||
fn fold(&mut self, e: FnExpr) -> FnExpr {
|
||||
let ident = if let Some(ident) = e.ident {
|
||||
Some(self.fold_binding_ident(ident))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let function = e.function.fold_with(self);
|
||||
|
||||
FnExpr { ident, function }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<FnDecl> for Resolver<'a> {
|
||||
fn fold(&mut self, node: FnDecl) -> FnDecl {
|
||||
let ident = self.fold_binding_ident(node.ident);
|
||||
|
||||
let function = node.function.fold_with(self);
|
||||
|
||||
FnDecl {
|
||||
ident,
|
||||
function,
|
||||
..node
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<Expr> for Resolver<'a> {
|
||||
fn fold(&mut self, expr: Expr) -> Expr {
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = false;
|
||||
let expr = match expr {
|
||||
// Leftmost one of a member expression shoukld be resolved.
|
||||
Expr::Member(me) => {
|
||||
if me.computed {
|
||||
Expr::Member(MemberExpr {
|
||||
obj: me.obj.fold_with(self),
|
||||
prop: me.prop.fold_with(self),
|
||||
..me
|
||||
})
|
||||
} else {
|
||||
Expr::Member(MemberExpr {
|
||||
obj: me.obj.fold_with(self),
|
||||
..me
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => expr.fold_children(self),
|
||||
};
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
|
||||
expr
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<VarDeclarator> for Resolver<'a> {
|
||||
fn fold(&mut self, decl: VarDeclarator) -> VarDeclarator {
|
||||
// order is important
|
||||
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = true;
|
||||
let name = decl.name.fold_with(self);
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
|
||||
let cur_name = match name {
|
||||
Pat::Ident(Ident { ref sym, .. }) => Some((sym.clone(), self.mark)),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let is_class_like = match decl.init {
|
||||
Some(box Expr::Fn(FnExpr { ref ident, .. }))
|
||||
if cur_name.is_some()
|
||||
&& ident.as_ref().map(|v| &v.sym) == cur_name.as_ref().map(|v| &v.0) =>
|
||||
{
|
||||
true
|
||||
}
|
||||
|
||||
Some(box Expr::Call(CallExpr {
|
||||
callee: ExprOrSuper::Expr(box Expr::Fn(FnExpr { ident: None, .. })),
|
||||
..
|
||||
}))
|
||||
| Some(box Expr::Call(CallExpr {
|
||||
callee:
|
||||
ExprOrSuper::Expr(box Expr::Paren(ParenExpr {
|
||||
expr: box Expr::Fn(FnExpr { ident: None, .. }),
|
||||
..
|
||||
})),
|
||||
..
|
||||
})) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if !is_class_like {
|
||||
dbg!(&decl.init);
|
||||
}
|
||||
|
||||
let old_def = self.cur_defining.take();
|
||||
self.cur_defining = if is_class_like { cur_name } else { None };
|
||||
|
||||
let init = decl.init.fold_children(self);
|
||||
|
||||
self.cur_defining = old_def;
|
||||
|
||||
VarDeclarator { name, init, ..decl }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<Ident> for Resolver<'a> {
|
||||
fn fold(&mut self, i: Ident) -> Ident {
|
||||
if self.in_var_decl {
|
||||
self.fold_binding_ident(i)
|
||||
} else {
|
||||
let Ident { span, sym, .. } = i;
|
||||
|
||||
if cfg!(debug_assertions) && LOG {
|
||||
eprintln!("resolver: IdentRef {}{:?}", sym, i.span.ctxt());
|
||||
}
|
||||
|
||||
if span.ctxt() != SyntaxContext::empty() {
|
||||
return Ident { sym, ..i };
|
||||
}
|
||||
|
||||
if let Some(mark) = self.mark_for(&sym) {
|
||||
if cfg!(debug_assertions) && LOG {
|
||||
eprintln!("\t -> {:?}", mark);
|
||||
}
|
||||
Ident {
|
||||
sym,
|
||||
span: span.apply_mark(mark),
|
||||
..i
|
||||
}
|
||||
} else {
|
||||
// Cannot resolve reference. (TODO: Report error)
|
||||
Ident { sym, span, ..i }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<ArrowExpr> for Resolver<'a> {
|
||||
fn fold(&mut self, e: ArrowExpr) -> ArrowExpr {
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = true;
|
||||
let params = e.params.fold_with(self);
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
|
||||
let body = e.body.fold_with(self);
|
||||
|
||||
ArrowExpr { params, body, ..e }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<Constructor> for Resolver<'a> {
|
||||
fn fold(&mut self, c: Constructor) -> Constructor {
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = true;
|
||||
let params = c.params.fold_with(self);
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
|
||||
let body = c.body.fold_with(self);
|
||||
let key = c.key.fold_with(self);
|
||||
|
||||
Constructor {
|
||||
params,
|
||||
body,
|
||||
key,
|
||||
..c
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<CatchClause> for Resolver<'a> {
|
||||
fn fold(&mut self, c: CatchClause) -> CatchClause {
|
||||
let old_in_var_decl = self.in_var_decl;
|
||||
self.in_var_decl = true;
|
||||
let param = c.param.fold_with(self);
|
||||
self.in_var_decl = old_in_var_decl;
|
||||
|
||||
let body = c.body.fold_with(self);
|
||||
|
||||
CatchClause { param, body, ..c }
|
||||
}
|
||||
}
|
602
ecmascript/transforms/src/compat/es2015/resolver/tests.rs
Normal file
602
ecmascript/transforms/src/compat/es2015/resolver/tests.rs
Normal file
@ -0,0 +1,602 @@
|
||||
use super::*;
|
||||
use crate::compat::es2015::block_scoping;
|
||||
|
||||
fn tr() -> impl Fold<Module> {
|
||||
chain!(resolver(), block_scoping())
|
||||
}
|
||||
|
||||
macro_rules! identical {
|
||||
($name:ident, $src:literal) => {
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
$name,
|
||||
$src,
|
||||
$src
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mark_for() {
|
||||
::testing::run_test(false, |_, _| {
|
||||
let mark1 = Mark::fresh(Mark::root());
|
||||
let mark2 = Mark::fresh(mark1);
|
||||
let mark3 = Mark::fresh(mark2);
|
||||
let mark4 = Mark::fresh(mark3);
|
||||
|
||||
let folder1 = Resolver::new(mark1, Scope::new(ScopeKind::Block, None), None);
|
||||
let mut folder2 = Resolver::new(
|
||||
mark2,
|
||||
Scope::new(ScopeKind::Block, Some(&folder1.current)),
|
||||
None,
|
||||
);
|
||||
folder2.current.declared_symbols.insert("foo".into());
|
||||
|
||||
let mut folder3 = Resolver::new(
|
||||
mark3,
|
||||
Scope::new(ScopeKind::Block, Some(&folder2.current)),
|
||||
None,
|
||||
);
|
||||
folder3.current.declared_symbols.insert("bar".into());
|
||||
assert_eq!(folder3.mark_for(&"bar".into()), Some(mark3));
|
||||
|
||||
let mut folder4 = Resolver::new(
|
||||
mark4,
|
||||
Scope::new(ScopeKind::Block, Some(&folder3.current)),
|
||||
None,
|
||||
);
|
||||
folder4.current.declared_symbols.insert("foo".into());
|
||||
|
||||
assert_eq!(folder4.mark_for(&"foo".into()), Some(mark4));
|
||||
assert_eq!(folder4.mark_for(&"bar".into()), Some(mark3));
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
basic_no_usage,
|
||||
"
|
||||
let foo;
|
||||
{
|
||||
let foo;
|
||||
}
|
||||
",
|
||||
"
|
||||
var foo;
|
||||
{
|
||||
var foo1;
|
||||
}
|
||||
"
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
class_nested_var,
|
||||
"
|
||||
var ConstructorScoping = function ConstructorScoping() {
|
||||
_classCallCheck(this, ConstructorScoping);
|
||||
var bar;
|
||||
{
|
||||
var bar;
|
||||
}
|
||||
}
|
||||
",
|
||||
"
|
||||
var ConstructorScoping = function ConstructorScoping() {
|
||||
_classCallCheck(this, ConstructorScoping);
|
||||
var bar;
|
||||
{
|
||||
var bar1;
|
||||
}
|
||||
}
|
||||
"
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
basic,
|
||||
r#"
|
||||
{
|
||||
var foo = 1;
|
||||
{
|
||||
let foo = 2;
|
||||
use(foo);
|
||||
}
|
||||
use(foo)
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
{
|
||||
var foo = 1;
|
||||
{
|
||||
var foo1 = 2;
|
||||
use(foo1);
|
||||
}
|
||||
use(foo);
|
||||
}
|
||||
"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
general_assignment_patterns,
|
||||
r#"const foo = "foo";
|
||||
|
||||
function foobar() {
|
||||
for (let item of [1, 2, 3]) {
|
||||
let foo = "bar";
|
||||
[bar, foo] = [1, 2];
|
||||
}
|
||||
}"#,
|
||||
r#"var foo = "foo";
|
||||
|
||||
function foobar() {
|
||||
for (var item of [1, 2, 3]) {
|
||||
var foo1 = "bar";
|
||||
[bar, foo1] = [1, 2];
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
general_function,
|
||||
r#"function test() {
|
||||
let foo = "bar";
|
||||
}"#,
|
||||
r#"function test() {
|
||||
var foo = "bar";
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
ignore,
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
babel_issue_1051,
|
||||
r#"foo.func1 = function() {
|
||||
if (cond1) {
|
||||
for (;;) {
|
||||
if (cond2) {
|
||||
function func2() {}
|
||||
function func3() {}
|
||||
func4(function() {
|
||||
func2();
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};"#,
|
||||
r#"foo.func1 = function () {
|
||||
if (cond1) {
|
||||
for (;;) {
|
||||
if (cond2) {
|
||||
var _ret = function () {
|
||||
function func2() {}
|
||||
|
||||
function func3() {}
|
||||
|
||||
func4(function () {
|
||||
func2();
|
||||
});
|
||||
return "break";
|
||||
}();
|
||||
|
||||
if (_ret === "break") break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};"#
|
||||
);
|
||||
|
||||
test!(
|
||||
ignore,
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
// TODO(kdy1): WTF is this (again)?
|
||||
tr(),
|
||||
babel_issue_2174,
|
||||
r#"if (true) {
|
||||
function foo() {}
|
||||
function bar() {
|
||||
return foo;
|
||||
}
|
||||
for (var x in {}) {}
|
||||
}"#,
|
||||
r#"
|
||||
if (true) {
|
||||
var foo = function () {};
|
||||
|
||||
var bar = function () {
|
||||
return foo;
|
||||
};
|
||||
|
||||
for (var x in {}) {}
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
ignore,
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
babel_issue_4363,
|
||||
r#"function WithoutCurlyBraces() {
|
||||
if (true)
|
||||
for (let k in kv) {
|
||||
function foo() { return this }
|
||||
function bar() { return foo.call(this) }
|
||||
console.log(this, k) // => undefined
|
||||
}
|
||||
}
|
||||
|
||||
function WithCurlyBraces() {
|
||||
if (true) {
|
||||
for (let k in kv) {
|
||||
function foo() { return this }
|
||||
function bar() { return foo.call(this) }
|
||||
console.log(this, k) // => 777
|
||||
}
|
||||
}
|
||||
}"#,
|
||||
r#"function WithoutCurlyBraces() {
|
||||
var _this = this;
|
||||
|
||||
if (true) {
|
||||
var _loop = function (k) {
|
||||
function foo() {
|
||||
return this;
|
||||
}
|
||||
|
||||
function bar() {
|
||||
return foo.call(this);
|
||||
}
|
||||
|
||||
console.log(_this, k); // => undefined
|
||||
};
|
||||
|
||||
for (var k in kv) {
|
||||
_loop(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function WithCurlyBraces() {
|
||||
var _this2 = this;
|
||||
|
||||
if (true) {
|
||||
var _loop2 = function (k) {
|
||||
function foo() {
|
||||
return this;
|
||||
}
|
||||
|
||||
function bar() {
|
||||
return foo.call(this);
|
||||
}
|
||||
|
||||
console.log(_this2, k); // => 777
|
||||
};
|
||||
|
||||
for (var k in kv) {
|
||||
_loop2(k);
|
||||
}
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
// Cannot represent function expression without parens (in result code)
|
||||
ignore,
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
babel_issue_4946,
|
||||
r#"(function foo() {
|
||||
let foo = true;
|
||||
});"#,
|
||||
r#"(function foo() {
|
||||
var foo = true;
|
||||
});"#
|
||||
);
|
||||
|
||||
// TODO: try {} catch (a) { let a } should report error
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
babel_issue_973,
|
||||
r#"let arr = [];
|
||||
for(let i = 0; i < 10; i++) {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
arr.push(() => i);
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"var arr = [];
|
||||
for(var i = 0; i < 10; i++){
|
||||
for(var i1 = 0; i1 < 10; i1++){
|
||||
arr.push(()=>i1);
|
||||
}
|
||||
}"#
|
||||
);
|
||||
|
||||
test_exec!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
pass_assignment,
|
||||
r#"let a = 1;
|
||||
a = 2;
|
||||
expect(a).toBe(2);"#
|
||||
);
|
||||
|
||||
test_exec!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
pass_call,
|
||||
r#"let a = 1;
|
||||
|
||||
function b() {
|
||||
return a + 1;
|
||||
}
|
||||
|
||||
expect(b()).toBe(2);"#
|
||||
);
|
||||
|
||||
test_exec!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
|_| tr(),
|
||||
pass_update,
|
||||
r#"let a = 1;
|
||||
a++;
|
||||
expect(a).toBe(2);"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
fn_param,
|
||||
r#"let a = 'foo';
|
||||
function foo(a) {
|
||||
use(a);
|
||||
}"#,
|
||||
r#"var a = 'foo';
|
||||
function foo(a1) {
|
||||
use(a1);
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
fn_body,
|
||||
r#"let a = 'foo';
|
||||
function foo() {
|
||||
let a = 'bar';
|
||||
use(a);
|
||||
}"#,
|
||||
r#"var a = 'foo';
|
||||
function foo() {
|
||||
var a1 = 'bar';
|
||||
use(a1);
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
shorthand,
|
||||
r#"let a = 'foo';
|
||||
function foo() {
|
||||
let a = 'bar';
|
||||
use({a});
|
||||
}"#,
|
||||
r#"var a = 'foo';
|
||||
function foo() {
|
||||
var a1 = 'bar';
|
||||
use({a: a1});
|
||||
}"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
same_level,
|
||||
r#"
|
||||
var a = 'foo';
|
||||
var a = 'bar';
|
||||
"#,
|
||||
r#"
|
||||
var a = 'foo';
|
||||
var a = 'bar';
|
||||
"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
class_block,
|
||||
r#"
|
||||
var Foo = function(_Bar) {
|
||||
_inherits(Foo, _Bar);
|
||||
function Foo() {
|
||||
}
|
||||
return Foo;
|
||||
}(Bar);
|
||||
"#,
|
||||
r#"
|
||||
var Foo = function(_Bar) {
|
||||
_inherits(Foo, _Bar);
|
||||
function Foo() {
|
||||
}
|
||||
return Foo;
|
||||
}(Bar);
|
||||
"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
class_block_2,
|
||||
r#"
|
||||
var Foo = (function(_Bar) {
|
||||
_inherits(Foo, _Bar);
|
||||
function Foo() {
|
||||
}
|
||||
return Foo;
|
||||
})(Bar);
|
||||
"#,
|
||||
r#"
|
||||
var Foo = function(_Bar) {
|
||||
_inherits(Foo, _Bar);
|
||||
function Foo() {
|
||||
}
|
||||
return Foo;
|
||||
}(Bar);
|
||||
"#
|
||||
);
|
||||
|
||||
test!(
|
||||
::swc_ecma_parser::Syntax::default(),
|
||||
tr(),
|
||||
class_nested,
|
||||
r#"
|
||||
var Outer = function(_Hello) {
|
||||
_inherits(Outer, _Hello);
|
||||
function Outer() {
|
||||
_classCallCheck(this, Outer);
|
||||
var _this = _possibleConstructorReturn(this, _getPrototypeOf(Outer).call(this));
|
||||
var Inner = function() {
|
||||
function Inner() {
|
||||
_classCallCheck(this, Inner);
|
||||
}
|
||||
_createClass(Inner, [{
|
||||
key: _get(_getPrototypeOf(Outer.prototype), 'toString', _assertThisInitialized(_this)).call(_this), value: function() {
|
||||
return 'hello';
|
||||
}
|
||||
}]);
|
||||
return Inner;
|
||||
}();
|
||||
return _possibleConstructorReturn(_this, new Inner());
|
||||
}
|
||||
return Outer;
|
||||
}(Hello);
|
||||
"#,
|
||||
r#"
|
||||
var Outer = function(_Hello) {
|
||||
_inherits(Outer, _Hello);
|
||||
function Outer() {
|
||||
_classCallCheck(this, Outer);
|
||||
var _this = _possibleConstructorReturn(this, _getPrototypeOf(Outer).call(this));
|
||||
var Inner = function() {
|
||||
function Inner() {
|
||||
_classCallCheck(this, Inner);
|
||||
}
|
||||
_createClass(Inner, [{
|
||||
key: _get(_getPrototypeOf(Outer.prototype), 'toString', _assertThisInitialized(_this)).call(_this), value: function() {
|
||||
return 'hello';
|
||||
}
|
||||
}]);
|
||||
return Inner;
|
||||
}();
|
||||
return _possibleConstructorReturn(_this, new Inner());
|
||||
}
|
||||
return Outer;
|
||||
}(Hello);
|
||||
"#
|
||||
);
|
||||
|
||||
identical!(class_var_constructor_only, r#"var Foo = function Foo(){}"#);
|
||||
|
||||
identical!(
|
||||
class_var,
|
||||
r#"
|
||||
var Foo = function(_Bar) {
|
||||
_inherits(Foo, _Bar);
|
||||
function Foo() {
|
||||
var _this;
|
||||
_classCallCheck(this, Foo);
|
||||
Foo[_assertThisInitialized(_this)];
|
||||
return _possibleConstructorReturn(_this);
|
||||
}
|
||||
return Foo;
|
||||
}(Bar);
|
||||
"#
|
||||
);
|
||||
|
||||
identical!(
|
||||
class_singleton,
|
||||
r#"
|
||||
var singleton;
|
||||
var Sub = function(_Foo) {
|
||||
_inherits(Sub, _Foo);
|
||||
function Sub() {
|
||||
var _this;
|
||||
_classCallCheck(this, Sub);
|
||||
if (singleton) {
|
||||
return _possibleConstructorReturn(_this, singleton);
|
||||
}
|
||||
singleton = _this = _possibleConstructorReturn(this, _getPrototypeOf(Sub).call(this));
|
||||
return _possibleConstructorReturn(_this);
|
||||
}
|
||||
return Sub;
|
||||
}(Foo);
|
||||
"#
|
||||
);
|
||||
|
||||
identical!(
|
||||
regression_001,
|
||||
"var sym = Symbol();
|
||||
|
||||
class Foo {
|
||||
[sym] () {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
class Bar extends Foo {
|
||||
[sym] () {
|
||||
return super[sym]() + 2;
|
||||
}
|
||||
}
|
||||
|
||||
var i = new Bar();
|
||||
|
||||
expect(i[sym]()).toBe(3);"
|
||||
);
|
||||
|
||||
identical!(
|
||||
regression_002,
|
||||
"var sym = Symbol();
|
||||
var Foo = function() {
|
||||
function Foo() {
|
||||
_classCallCheck(this, Foo);
|
||||
}
|
||||
_createClass(Foo, [{
|
||||
key: sym, value: function() {
|
||||
return 1;
|
||||
}
|
||||
}]);
|
||||
return Foo;
|
||||
}();
|
||||
var Bar = function(_Foo) {
|
||||
_inherits(Bar, _Foo);
|
||||
function Bar() {
|
||||
_classCallCheck(this, Bar);
|
||||
return _possibleConstructorReturn(this, _getPrototypeOf(Bar).apply(this, arguments));
|
||||
}
|
||||
_createClass(Bar, [{
|
||||
key: sym, value: function() {
|
||||
return _get(_getPrototypeOf(Bar.prototype), sym, this)() + 2;
|
||||
}
|
||||
}]);
|
||||
return Bar;
|
||||
}(Foo);
|
||||
var i = new Bar();
|
||||
expect(i[sym]()).toBe(3);"
|
||||
);
|
@ -87,9 +87,11 @@ impl Fold<Expr> for Spread {
|
||||
|
||||
Expr::New(NewExpr {
|
||||
span,
|
||||
callee: box member_expr!(span, Function.prototype.bind)
|
||||
.apply(span, callee, vec![args.as_arg()])
|
||||
.wrap_with_paren(),
|
||||
callee: box member_expr!(span, Function.prototype.bind).apply(
|
||||
span,
|
||||
callee,
|
||||
vec![args.as_arg()],
|
||||
),
|
||||
args: Some(vec![]),
|
||||
type_args,
|
||||
})
|
||||
@ -234,8 +236,9 @@ mod tests {
|
||||
Spread::default(),
|
||||
new,
|
||||
"new C(a, b, c, ...d, e)",
|
||||
"new (Function.prototype.bind.apply(C, [null, a, b, c].concat(_toConsumableArray(d), \
|
||||
[e])))();"
|
||||
"new Function.prototype.bind.apply(C, [null, a, b, c].concat(_toConsumableArray(d), \
|
||||
[e]))();",
|
||||
ok_if_code_eq
|
||||
);
|
||||
|
||||
test!(
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{helpers::Helpers, util::ExprFactory};
|
||||
use ast::*;
|
||||
use std::{iter, sync::Arc};
|
||||
use swc_common::{Fold, FoldWith, Mark, Spanned, DUMMY_SP};
|
||||
use swc_common::{Fold, FoldWith, Spanned, DUMMY_SP};
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
@ -70,8 +70,7 @@ impl Fold<Expr> for TemplateLiteral {
|
||||
assert!(quasis.len() == exprs.len() + 1);
|
||||
self.helpers.tagged_template_literal();
|
||||
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
let fn_ident = quote_ident!(DUMMY_SP.apply_mark(mark), "_templateObject");
|
||||
let fn_ident = private_ident!("_templateObject");
|
||||
|
||||
let tpl_obj_fn = {
|
||||
Expr::Fn(FnExpr {
|
||||
|
@ -3,7 +3,7 @@ use crate::{
|
||||
util::{ExprFactory, StmtLike},
|
||||
};
|
||||
use ast::*;
|
||||
use swc_common::{Fold, FoldWith, Mark, Span, Spanned, Visit, VisitWith, DUMMY_SP};
|
||||
use swc_common::{Fold, FoldWith, Span, Spanned, Visit, VisitWith, DUMMY_SP};
|
||||
|
||||
/// `@babel/plugin-transform-exponentiation-operator`
|
||||
///
|
||||
@ -52,15 +52,15 @@ impl Fold<Expr> for AssignFolder {
|
||||
|
||||
// unimplemented
|
||||
PatOrExpr::Expr(ref e) => {
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
let span = e.span().apply_mark(mark);
|
||||
let ref_ident = private_ident!(e.span(), "ref");
|
||||
|
||||
self.vars.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: quote_ident!(span, "ref").into(),
|
||||
name: ref_ident.clone().into(),
|
||||
init: Some(e.clone()),
|
||||
definite: false,
|
||||
});
|
||||
quote_ident!(span, "ref")
|
||||
ref_ident
|
||||
}
|
||||
|
||||
left => {
|
||||
|
@ -487,8 +487,7 @@ impl Actual {
|
||||
let params = f.params.clone();
|
||||
let ident = raw_ident.clone().unwrap_or_else(|| quote_ident!("ref"));
|
||||
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
let real_fn_ident = quote_ident!(ident.span.apply_mark(mark), format!("_{}", ident.sym));
|
||||
let real_fn_ident = private_ident!(ident.span, format!("_{}", ident.sym));
|
||||
let right = make_fn_ref(
|
||||
&self.helpers,
|
||||
FnExpr {
|
||||
|
@ -49,7 +49,7 @@ let TestClass = {
|
||||
let TestClass = {
|
||||
name: 'John Doe',
|
||||
testMethodFailure () {
|
||||
return new Promise((function(resolve) {
|
||||
return new Promise(function(resolve) {
|
||||
var _ref = _asyncToGenerator((function*(resolve) {
|
||||
console.log(this);
|
||||
setTimeout(resolve, 1000);
|
||||
@ -57,7 +57,7 @@ let TestClass = {
|
||||
return function() {
|
||||
return _ref.apply(this, arguments);
|
||||
};
|
||||
})().bind(this));
|
||||
}().bind(this));
|
||||
}
|
||||
};
|
||||
"#
|
||||
@ -181,29 +181,29 @@ function _s() {
|
||||
for(let _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++){
|
||||
args[_key - 1] = arguments[_key];
|
||||
}
|
||||
let t = (function(y, a) {
|
||||
var _t = _asyncToGenerator((function*(y, a) {
|
||||
let r = (function(z, b) {
|
||||
var _ref = _asyncToGenerator((function*(z, b) {
|
||||
for(let _len = arguments.length, innerArgs = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++){
|
||||
innerArgs[_key - 2] = arguments[_key];
|
||||
let t = function(y, a) {
|
||||
var _ref = _asyncToGenerator((function*(y, a) {
|
||||
let r = function(z, b) {
|
||||
var _ref1 = _asyncToGenerator((function*(z, b) {
|
||||
for(let _len1 = arguments.length, innerArgs = new Array(_len1 > 2 ? _len1 - 2 : 0), _key1 = 2; _key1 < _len1; _key1++){
|
||||
innerArgs[_key1 - 2] = arguments[_key1];
|
||||
}
|
||||
yield z;
|
||||
console.log(this, innerArgs, arguments);
|
||||
return this.x;
|
||||
}).bind(this));
|
||||
return function() {
|
||||
return _ref.apply(this, arguments);
|
||||
return _ref1.apply(this, arguments);
|
||||
};
|
||||
})().bind(this);
|
||||
}().bind(this);
|
||||
yield r();
|
||||
console.log(this, args, arguments);
|
||||
return this.g(r);
|
||||
}).bind(this));
|
||||
return function t() {
|
||||
return _t.apply(this, arguments);
|
||||
return function () {
|
||||
return _ref.apply(this, arguments);
|
||||
};
|
||||
})().bind(this);
|
||||
}().bind(this);
|
||||
yield t();
|
||||
return this.h(t);
|
||||
}).bind(this));
|
||||
@ -296,7 +296,7 @@ function two(a, b) {
|
||||
}
|
||||
function _three() {
|
||||
_three = _asyncToGenerator(function*(a, param, c, param1) {
|
||||
let tmp = param, b = tmp === void 0 ? 1 : tmp, tmp = param1, d = tmp === void 0 ? 3 : tmp;
|
||||
let tmp = param, b = tmp === void 0 ? 1 : tmp, tmp1 = param1, d = tmp1 === void 0 ? 3 : tmp1;
|
||||
});
|
||||
return _three.apply(this, arguments);
|
||||
}
|
||||
@ -327,7 +327,7 @@ function five(a, param) {
|
||||
function _six() {
|
||||
_six = _asyncToGenerator(function*(a, param) {
|
||||
let tmp = param, ref = tmp === void 0 ? {
|
||||
} : tmp, ref = ref ? ref : _throw(new TypeError("Cannot destructure 'undefined' or 'null'")), b = ref.b;
|
||||
} : tmp, ref1 = ref ? ref : _throw(new TypeError("Cannot destructure 'undefined' or 'null'")), b = ref1.b;
|
||||
});
|
||||
return _six.apply(this, arguments);
|
||||
}
|
||||
@ -347,14 +347,14 @@ var foo = async function bar() {
|
||||
};
|
||||
"#,
|
||||
r#"
|
||||
var foo = (function() {
|
||||
var foo = function() {
|
||||
var _bar = _asyncToGenerator(function*() {
|
||||
console.log(bar);
|
||||
});
|
||||
return function bar() {
|
||||
return _bar.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
}();
|
||||
"#
|
||||
);
|
||||
|
||||
@ -366,13 +366,13 @@ test!(
|
||||
foo(async function () {
|
||||
});"#,
|
||||
r#"
|
||||
foo((function() {
|
||||
foo(function() {
|
||||
var _ref = _asyncToGenerator(function*() {
|
||||
});
|
||||
return function() {
|
||||
return _ref.apply(this, arguments);
|
||||
};
|
||||
})());
|
||||
}());
|
||||
"#
|
||||
);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user