Skip to content

typeof someFun() erroneously collapses to typeof globalVar when inlined #3498

@sjrd

Description

@sjrd

This is quite the corner case. It produces code that behaves differently depending on whether a function call is inlined or not.

Reproducer:

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @output_file_name default.js
// @formatting pretty_print
// ==/ClosureCompiler==

function testInlined() {
  return thisVarDoesNotExist;
}

/** 
 * @noinline
 */
function testNotInlined() {
  return thisVarDoesNotExist;
}

function test(f) {
  try {
    console.log(f());
  } catch (e) {
    console.log(e);
  }
}

test(() => typeof thisVarDoesNotExist);
test(() => typeof testInlined());
test(() => typeof testNotInlined());

link to the online compiler

The (pretty-printed) compiled code is:

function a() {
  return thisVarDoesNotExist;
}
function b(c) {
  try {
    console.log(c());
  } catch (d) {
    console.log(d);
  }
}
b(function() {
  return typeof thisVarDoesNotExist;
});
b(function() {
  return typeof thisVarDoesNotExist;
});
b(function() {
  return typeof a();
});

The original code prints:

undefined
ReferenceError: thisVarDoesNotExist is not defined
ReferenceError: thisVarDoesNotExist is not defined

as it should, but the compiled code prints:

undefined
undefined
ReferenceError: thisVarDoesNotExist is not defined

The problem is that, when inlining testInlined() in the expression typeof testInlined(), the compiler forgot to protect the reference to the non-existent global reference to thisVarDoesNotExist, resulting in

typeof thisVarDoesNotExist

This changes the semantics of the evaluation, because a typeof whose direct argument is a reference to a non-existent global variable returns "undefined" instead of throwing a ReferenceError.

A correct translation would be to protect the inlined argument to typeof with:

typeof (0, thisVarDoesNotExist)

Metadata

Metadata

Assignees

No one assigned

    Labels

    internal-issue-createdAn internal Google issue has been created to track this GitHub issuetriage-doneHas been reviewed by someone on triage rotation.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions