I think the appropriate term for this is a pretty-printer. It isn't really a compiler, because the target language is the same as the source.
For a JavaScript compiler (or VM) to be genuinely described as self-hosting, it would need to be able to run using itself, without depending on an existing implementation such as V8, ChakraCore etc. The hard part is not outputting code that can be evaluated by JS itself, but implementing the semantics of JS in terms of a lower-level of abstraction, ideally native code.
> It isn't really a compiler, because the target language is the same as the source.
I think it could still be deemed a "compiler" even if it output the same language if it was doing some significant transformation or modification of it.
But, yes, in this case I think you're right and a "pretty-printer" is a better description of it.
'Pretty-printer' is not quite right either. Nobody bootstraps pretty-printers by repeatedly running them through themselves and extending them which I think was kind of the point of the exercise here.
What is the best way known to implement the semantics of a language? Generating an abstract syntax tree is nice, but what is the state of the art in abstract semantics ?
The immediate question I had was: "compiles JS to what"?
Apparently the answer is: to Javascript. It's what some call a transpiler: it compiles Javascript plus some extra features down to a more "vanilla" Javascript (es5?). I tend to dislike the term transpiler (transpilers are just compilers that target high-level languages), but I guess in this case the term would have helped me understand what was meant!
I really like Douglas Crockford's Pratt parser which is similar. It doesn't compile down to JS but it's trivial to go from the AST to JS either manually or using something like escodegen.
For a JavaScript compiler (or VM) to be genuinely described as self-hosting, it would need to be able to run using itself, without depending on an existing implementation such as V8, ChakraCore etc. The hard part is not outputting code that can be evaluated by JS itself, but implementing the semantics of JS in terms of a lower-level of abstraction, ideally native code.