Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function referencing variables in temporal dead zone cannot be serialized #323

Open
overlookmotel opened this issue Dec 4, 2021 · 0 comments
Labels
bug Something isn't working

Comments

@overlookmotel
Copy link
Owner

Problem

Input:

export default ( () => {
  return y => y || x;
  const x = 1;
} )();

This function returns true if called with argument true. Otherwise, it throws an error as it attempts to access x before initialization.

Trying to serialize this throws error Failed to extract scope vars from function.

Cause

The TDZ error is thrown in the tracker function as it tries to access x.

(y) => {
  livepack_tracker(
    /*livepack_track:{"id":3,"scopes":[{"blockId":2,"varNames":["x"]}],"isStrict":true}*/
    () => [[livepack_scopeId_2, x]]
  );
  return y || x;
}

Solution

Would need tracker function to return array of getters rather than vars:

livepack_tracker( () => [[livepack_scopeId_2, () => x]] );

When calling () => x to obtain value of x, can catch error which would indicate if it's not yet initialized.

NB Need an individual function for each var, as some vars may be in TDZ, and some not.

Serialized function would be:

function _throwTdzError (name) {
  throw new Error(`Cannot access '${name}' before initialization`);
}
export default y => y || _throwTdzError('x');

If var is only sometimes in TDZ, throwing error would need to be conditional:

// Input
function outer(exitEarly) {
  const fn = (0, y => y || x);
  if (exitEarly) return fn;
  const x = 123;
  return fn;
}
export default [ outer(true), outer(false) ];
// Output
function _throwTdzError (name) {
  throw new Error(`Cannot access '${name}' before initialization`);
}
const createScope = (_isDeadX, x) => y => y || (_isDeadX ? _throwTdzError('x') : x);
export default [ createScope(1), createScope(0, 123) ];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant