Reserved JavaScript

41

5

As of ECMAScript 2015, JavaScript has 33 reserved keywords, such as break, const and new, as well as 10 future reserved keywords, such as let and await.

Your task is to chain together the largest number of consecutive1 distinct reserved keywords2 while writing functional JavaScript code3.

  1. Consecutive reserved keywords - reserved keywords that are separated only by whitespace and/or parentheses and/or curly braces.
  2. Reserved keywords - any reserved or future reserved keywords as of ECMAScript 2015. Reserved keywords from older standards are excluded, a full list of allowed keywords is given below.
  3. Functional code - your code should run (state your runtime, if necessary), eventually halt, and not throw any runtime errors.

If your code needs a specific runtime, the used reserved keywords must not be no-ops in the given environment.

List of reserved keywords

await
break
case
catch
class
const
continue
debugger
default
delete
do
else
enum
export
extends
finally
for
function
if
implements
import
in
instanceof
interface
let
new
package
private
protected
public
return
static
super
switch
this
throw
try
typeof
var
void
while
with
yield

Scoring & examples

Your score will be equal to the largest number of consecutive distinct reserved keywords.
In the case of equal scores, shortest source code in bytes wins. Commented sections and strings don't count towards reserved keywords, but count towards byte count.

// score: 3
if (true) 0; else throw function() {}
             ^------------------^
// score: 2
let foo = typeof typeof void typeof void 0;
                             ^---------^
// score: 0
/* typeof default debugger */

// score: 0, doesn't halt or debugger is no-op, depending on the environment
debugger;

Standard loopholes apply.

Nit

Posted 2018-04-03T23:05:36.413

Reputation: 2 667

Sandbox discussion, for those who are interested. – Nit – 2018-04-03T23:07:03.610

I feel like this might be more interesting if you did not allow parentheses between the keywords. – Post Rock Garf Hunter – 2018-04-03T23:56:09.003

Is newline allowed? – l4m2 – 2018-04-04T02:54:38.780

@l4m2 Yes, it's whitespace. – Nit – 2018-04-04T07:13:29.383

Now that 43-score solution exist... – l4m2 – 2018-04-04T09:40:11.563

1@l4m2 The same 43-point solution is possible without newlines as well so perhaps I simply don't understand the point you're trying to make? – Nit – 2018-04-04T09:59:01.333

In the case of equal scores, shortest source code in bytes wins. The common solution uses 4 extra chars for each word but sometimes it can do better – l4m2 – 2018-04-04T10:00:51.627

Let us continue this discussion in chat.

– l4m2 – 2018-04-04T10:00:53.593

@msh210 Thanks, I didn't know tags are used like that on PCG, updated. – Nit – 2018-04-05T07:57:55.453

Answers

53

37 words

if (void this) {
  do {
    with (protected)
      for (public in private)
        typeof static instanceof new (function implements() {
          var let
          try {
            throw (class extends {} {})
          } catch (package) {
            yield
          } finally {
            debugger
          }
          return
        })()
    continue
    break
  } while (interface)
} else {
  switch (delete await) { default : 42 }
}

Keywords not used:

  • case requires :
  • const requires =
  • export requires strict mode
  • import requires strict mode
  • super requires constructor

tsh

Posted 2018-04-03T23:05:36.413

Reputation: 13 072

7I admit I laughed – nicael – 2018-04-04T07:09:13.217

48It looks like typical Java boilerplate code, e.g. to calculate 1 + 2. – Eric Duminil – 2018-04-04T08:14:57.133

2@EricDuminil This is the real reason it's called _Java_​Script. – wizzwizz4 – 2018-04-04T08:23:29.073

5@EricDuminil That's not quite simple as 1 + 2. The complete value of this code is the answer to the ultimate question of life, the universe and everything. That's complex. :) – tsh – 2018-04-04T09:56:18.787

2This is just wonderful. – Pedro A – 2018-04-04T10:09:03.820

@apsillers that's not a dumb thing to do at all. In fact it's preferable to using let or var. Remember that const and let have more reasonable scoping than var; the variable defined is scoped to the loop body, not the function, so if it stays constant within an iteration, then const is fine. – Dave – 2018-04-06T23:08:54.740

@Dave Yeah, I realized that I was wrong today when I was running my entry -- a const loop var is usually very good practice – apsillers – 2018-04-07T01:57:22.830

53

43 words, 603 bytes

Uhm, is this a loophole? I have no idea how the hell this is legal JS, but it works and it uses every single keyword.

new (class await
{
    break(){}
    case(){}
    catch(){}
    const(){}
    continue(){}
    debugger(){}
    default(){}
    delete(){}
    do(){}
    else(){}
    enum(){}
    export(){}
    extends(){}
    finally(){}
    for(){}
    function(){}
    if(){}
    implements(){}
    import(){}
    in(){}
    instanceof(){}
    interface(){}
    let(){}
    package(){}
    private(){}
    protected(){}
    public(){}
    return(){}
    static(){}
    super(){}
    switch(){}
    this(){}
    throw(){}
    try(){}
    typeof(){}
    var(){}
    void(){}
    while(){}
    with(){}
    yield(){}
})

Siguza

Posted 2018-04-03T23:05:36.413

Reputation: 719

3Not that familiar with JS, but... are these actually keywords when used in this context, or just strings that have the same lexical structure as keywords and are using sugar to avoid quotes? – Leushenko – 2018-04-04T09:07:58.920

1@Leushenko Probably the second (although I'm also not too familiar with JS at all), as they look like function names in the way they are used. Still, normally it shouldn't be possible to use these keywords as functions or class names, but Siguza still did it, while still complying to the challenge rules of only using parenthesis and brackets. A nice find to complete this challenge with all words I'd say, even though most of the other answers look more impressive for actually using the keywords AS keywords. Still +1 from me, it seems we have a winner. – Kevin Cruijssen – 2018-04-04T09:19:34.450

Of course you can make the answer more interesting by moving some of the keywords into the function body. Why not? – user202729 – 2018-04-04T09:20:41.760

6@user202729 Why though? Why make it overly complexly looking when it can be done so simple? Code-golfing is usually doing something as short as possible, but I personally still prefer to keep readability and simplicity to some extend (I know, I know, this isn't a code-golfing challenge). Some examples: I prefer to use -1, i+1, i-1 above ~0, -~i, ~-i when I can, just because it's clearer to read for those who aren't too familiar with code-golfing and ~ yet. Although I will of course always use i+~j and i-~j to golf that single byte of i-j-1 and i+j+1. ;) – Kevin Cruijssen – 2018-04-04T09:25:28.753

2Yes, I could mash it further, and try to get the byte count down... a beginning like if(this)return void typeof function(){} else debugger isn't hard to come up with, but after that it gets ugly fast. And yes, this totally turns keywords into identifiers - but for some of them you have to in order to be able to use them (e.g. enum). I just took it to the extreme, but isn't that what code golfing is all about? :P – Siguza – 2018-04-04T09:35:50.087

Are you... literally redefining the function of keywords? – Magic Octopus Urn – 2018-04-05T23:10:07.277

1@Magic No, supplying the name of a class-method is simply a grammatical context where literal tokens are treated as property names, even if they are reserved words. This is basically the same, semantically, as doing obj["break"] = function (){} etc. – apsillers – 2018-04-06T01:17:05.493

@KevinCruijssen Because not attempting further golfing means this one actually loses, as ties are broken by bytecount. – trlkly – 2018-04-07T08:50:26.523

Save tons of bytes: Eliminate the leading spaces in front of each line – OldBunny2800 – 2018-04-07T18:47:32.570

30

43 words, 302 299 bytes

switch(void function(){for(const interface in public)do with(package)try{break}catch(private){if(typeof
this)throw yield static instanceof new class extends await{case(){return}super(){debugger}import(){}export(){}enum(){}}
else continue}finally{delete let}while(protected)var implements}){default:}

l4m2

Posted 2018-04-03T23:05:36.413

Reputation: 5 985

Theoretical lowerbound 277 (each two words separated by one byte) – l4m2 – 2018-04-04T10:13:46.170

Nice work, currently you're only missing enum. – Nit – 2018-04-04T10:16:35.863

10

21 24 26 words, 185 bytes

+1 2 words thanks to Arnauld, and +1 to 12Me21!

void(function(){do{with({})if(typeof true in this)throw{}instanceof new(class extends{}{})
else return delete{}
try{break}finally{yield}
continue
}while(false)})()
switch({}){case{}:{}}

Assuming I understood the challenge, this scores 24 words. The words without parentheses, brackets, and whitespace:

void function do with if typeof true in this throw instanceof new class extends else return delete try break finally yield continue while false switch case

24 words, 177 bytes

Without "true" and "false", which are apparently not keywords according to the question.

void(function(){do{with({})if(typeof{}in this)throw{}instanceof new(class extends{}{})
else return{}
try{break}finally{yield}
continue
}while(delete{})})()
switch({}){case{}:{}}

Words:

void function do with if typeof in this throw instanceof new class extends else return try break finally yield continue while delete switch case

Conor O'Brien

Posted 2018-04-03T23:05:36.413

Reputation: 36 228

(I accidentally deleted my comment instead of editing it, the contents were: "you can use delete{} in place of true/false, think (and just return nothing") – 12Me21 – 2018-04-04T00:06:33.473

Ah, yes. I didn't pay much attention to that rule. – Arnauld – 2018-04-04T00:09:16.000

you can put case ... : or default: at the end (since : isn't allowed between keywords) – 12Me21 – 2018-04-04T00:15:49.243

Ot you can end with for(let _;0;); for +2 words (but you can't use case anymore). – Arnauld – 2018-04-04T00:38:18.720

switch({}){case{}:{}} => switch({}){case{}:;}? Not know if ; is sometimes necessary – l4m2 – 2018-04-04T02:47:21.860

6

38 39

class await {}
class g extends await {
 constructor() {
  super()
 }
}
switch ({}) {
 case function(){
  for (let in public)
  do with(package){
   try{break}catch(private){
   if(typeof this)
    throw static instanceof new (class extends await {})
   else{continue}}finally{debugger}
  }while(void protected)
  var implements
  return 
  yield delete interface
  const a=0
 }:
}

words from "super" to "const"

Golfed version:

class e{}class g extends e{constructor(){super()}}switch({}){case
function(){for(let in public)do with(package)try{break}catch(private){if(typeof
this)throw static instanceof new(class extends await{})
else{continue}}finally{debugger}while(void protected)
var implements
return 
yield delete interface
const a=0}:}

l4m2

Posted 2018-04-03T23:05:36.413

Reputation: 5 985

Is it now golfing time? – l4m2 – 2018-04-04T04:25:01.140

I'm getting Uncaught SyntaxError: Unexpected token delete when I try to run your answer in my Javascript console on Google Chrome, How can I test if your solution is valid? – Ferrybig – 2018-04-06T17:51:39.057

@Ferrybig I use Firefox and it works fine. I can't install new version Chrome because of system – l4m2 – 2018-04-07T00:08:27.457

I get this error in Firefox SyntaxError: yield expression is only valid in generators – TheChetan – 2018-04-08T06:28:50.693

I use ff 52.7.2 – l4m2 – 2018-04-08T06:51:51.843

4

21 words

(not sure about let and await)

var await=String, let=String;
switch (await) {
    case void typeof new await instanceof let in (function()
{do{try{return this
if((class extends{}{})){}else{break}}finally{(delete {})}}while(false)})():break;
}

soktinpk

Posted 2018-04-03T23:05:36.413

Reputation: 4 080

, = and ; are not allowed as separators. – user202729 – 2018-04-04T09:24:21.433

2They aren't being counted – soktinpk – 2018-04-04T15:20:21.473

3

14 15 16 Words with no brackets or newline

!function(){if(0);else do throw yield new public in void typeof this instanceof class await extends function async(){}{};while(0)}

Thank Bergi for +1

l4m2

Posted 2018-04-03T23:05:36.413

Reputation: 5 985

Can you make it a generator function and throw in a yield? – Bergi – 2018-04-05T17:49:20.807

I tried to figure out what this does, but my head started spinning. Could you post an explanation? – Philipp – 2018-04-06T17:01:44.067

I'm getting Uncaught SyntaxError: Unexpected token new when I paste inside my javascript console – Ferrybig – 2018-04-06T17:49:42.610

1@Ferrybig, replace function with function*, so it will be recognized as a generator. – guest-418 – 2018-04-06T19:28:49.440

3

43 words, 300 bytes

with(this)try{let protected}catch(package){if(delete yield)for(const interface in typeof public)do{throw implements instanceof private}while(static)else debugger}finally{switch(void new class extends function(){return}{export(){var await}import(){break}super(){continue}enum(){}case(){}}){default:0}}

More readably:

with(this)
    try {
        let protected
    } catch(package){
        if(delete yield)
            for(const interface in typeof public)
                do {
                    throw implements instanceof private
                } while(static)
        else
            debugger
    } finally {
        switch(
          void new class extends function(){return} {
              export(){var await}
              import(){break}
              super(){continue}
              enum(){}
              case(){}
          }
        ){
            default:0
        }
    }

I had to use the "reserved word as method name" to deal with

  • case (since I had already used default with my swtich),
  • export and import (since module-mode is always strict, which disqualifies with)
  • super (since it must be followed by a property access or placed in a constructor function), and
  • enum (which can never be used at all, being a reserved word with no grammatically-valid use)

apsillers

Posted 2018-04-03T23:05:36.413

Reputation: 3 632

My 39 solution shows super can appear in the beginning without being name, but too expensive – l4m2 – 2018-04-05T18:03:18.127

2

28 Words without brackets, 234 Bytes

Putting identifier names as method definition names was too obvious (for me at least), so I was looking for the longest consecutive distinct sequence of reserved words and whitespace in a code snippet.

I hope dead code after a return doesn't count as a loophole, but the code is still runnable if the used identifiers are declared.

function*_(){implements:{
let private
var public
return yield typeof static
delete protected
throw new interface in package
break implements
debugger
void this instanceof class await extends function async(){}{}
do
continue
while(0)}}

This exploits the fact that some of the future reserved keywords are only considered invalid in ES5.1's strict mode (apparently because engines didn't bother to block all of ES3's future reserved words so there was too much code using them out there on the web).

Similarly, the async and await tokens introduced in ES8 are only considered keywords in strict mode.

Bergi

Posted 2018-04-03T23:05:36.413

Reputation: 967

Can break and continue be there? – l4m2 – 2018-04-05T16:46:13.410

When I call the function, I get Uncaught SyntaxError: Undefined label 'implements', does your answer require a specific runtime? – Nit – 2018-04-05T16:49:30.147

@Nit Oops, I didn't actually call it, I only checked whether it's syntactically allowed (and then optimised prosaicism :D). – Bergi – 2018-04-05T17:44:21.547

@l4m2 Oh, you're right, they can't but it's a runtime error so I didn't notice :-( Needed a bit of arbitrary reordering to work (and a block with the label). – Bergi – 2018-04-05T17:45:31.327

@Bergi On Firefox it's syntax error on tio nodejs it's runtime – l4m2 – 2018-04-05T17:50:12.433