Stage 1 Draft / January 13, 2021

Dynamic Code Brand Checks

1 Runtime Semantics: IsCodeLike ( x )

The abstract operation IsCodeLike with arguments x checks if x contains the host-defined [[HostDefinedCodeLike]] internal slot. It performs the following steps:

  1. If x has a [[HostDefinedCodeLike]] internal slot, and Type(x.[[HostDefinedCodeLike]]) is String then return true.
  2. Return false.
Note
Hosts should ascertain that [[HostDefinedCodeLike]] internal slot value for objects doesn't change. This is to allow for passing code-like objects without handing out capabilities to change the code that they wrap.

2 HostEnsureCanCompileStrings HostValidateDynamicCode ( callerRealm, calleeRealm, codeString, wasCodeLike, compilationSink)

HostEnsureCanCompileStrings HostValidateDynamicCode is a host-defined abstract operation that takes arguments callerRealm (a Realm), calleeRealm (a Realm), codeString (a string), wasCodeLike (a boolean), and compilationSink ("Function" or "eval") and allows host environments to blockguard certain ECMAScript functions which allow developers to compile strings into ECMAScript code.

An implementation of HostEnsureCanCompileStrings HostValidateDynamicCode may complete normally or abruptly. Any normal completion must return a String. Any abrupt completions will be propagated to its callers. The default implementation of HostEnsureCanCompileStringsHostValidateDynamicCode is to unconditionally return a empty normal completionNormalCompletion(codeString).

3 Runtime Semantics: PerformEval ( x, callerRealm, strictCaller, direct )

The abstract operation PerformEval with arguments x, callerRealm, strictCaller, and direct performs the following steps:

  1. Assert: If direct is false, then strictCaller is also false.
  2. Let isCodeLike be ! IsCodeLike(x).
  3. If isCodeLike is true, set x to x.[[HostDefinedCodeLike]].
  4. If Type(x) is not String, return x.
  5. Let evalRealm be the current Realm Record.
  6. Perform ? HostEnsureCanCompileStrings(callerRealm, calleeRealm).
    Set x to be ? HostValidateDynamicCode(callerRealm, calleeRealm, x, isCodeLike, "eval").
  7. ...

4 CreateDynamicFunction ( constructor, newTarget, kind, args )

The abstract operation CreateDynamicFunction takes arguments constructor (a constructor), newTarget (a constructor), kind (either normal, generator, async, or asyncGenerator), and args (a List of ECMAScript language values). constructor is the constructor function that is performing this action. newTarget is the constructor that new was initially applied to. args is the argument values that were passed to constructor. It performs the following steps when called:

  1. Assert: The execution context stack has at least two elements.
  2. Let callerContext be the second to top element of the execution context stack.
  3. Let callerRealm be callerContext's Realm.
  4. Let calleeRealm be the current Realm Record.
  5. Perform ? HostEnsureCanCompileStrings(callerRealm, calleeRealm).
  6. If newTarget is undefined, set newTarget to constructor.
  7. If kind is normal, then
    1. Let goal be the grammar symbol FunctionBody[~Yield, ~Await].
    2. Let parameterGoal be the grammar symbol FormalParameters[~Yield, ~Await].
    3. Let fallbackProto be "%Function.prototype%".
  8. Else if kind is generator, then
    1. Let goal be the grammar symbol GeneratorBody.
    2. Let parameterGoal be the grammar symbol FormalParameters[+Yield, ~Await].
    3. Let fallbackProto be "%GeneratorFunction.prototype%".
  9. Else if kind is async, then
    1. Let goal be the grammar symbol AsyncFunctionBody.
    2. Let parameterGoal be the grammar symbol FormalParameters[~Yield, +Await].
    3. Let fallbackProto be "%AsyncFunction.prototype%".
  10. Else,
    1. Assert: kind is asyncGenerator.
    2. Let goal be the grammar symbol AsyncGeneratorBody.
    3. Let parameterGoal be the grammar symbol FormalParameters[+Yield, +Await].
    4. Let fallbackProto be "%AsyncGeneratorFunction.prototype%".
  11. Let argCount be the number of elements in args.
  12. Let P be the empty String.
  13. Let assembledFromCodeLike be true.
  14. If argCount = 0, let bodyArg be the empty String.
  15. Else if argCount = 1, let bodyArg be args[0].
    1. Let bodyArg be args[0].
    2. If IsCodeLike(bodyArg) is true, set bodyArg to bodyArg.[[HostDefinedCodeLike]]. Otherwise, set assembledFromCodeLike to false.
  16. Else,
    1. Assert: argCount > 1.
    2. Let firstArg be args[0].
    3. If IsCodeLike(firstArg) is true, set firstArg to firstArg.[[HostDefinedCodeLike]]. Otherwise, set assembledFromCodeLike to false.
    4. Set P to ? ToString(firstArg).
    5. Let k be 1.
    6. Repeat, while k < argCount - 1,
      1. Let nextArg be args[k].
      2. If IsCodeLike(nextArg) is true, set nextArg to nextArg.[[HostDefinedCodeLike]]. Otherwise, set assembledFromCodeLike to false.
      3. Let nextArgString be ? ToString(nextArg).
      4. Set P to the string-concatenation of P, "," (a comma), and nextArgString.
      5. Set k to k + 1.
    7. Let bodyArg be args[k].
    8. If IsCodeLike(bodyArg) is true, set bodyArg to bodyArg.[[HostDefinedCodeLike]]. Otherwise, set assembledFromCodeLike to false.
  17. Let bodyString be the string-concatenation of 0x000A (LINE FEED), ? ToString(bodyArg), and 0x000A (LINE FEED).
  18. Let prefix be the prefix associated with kind in Table 50.
  19. Let sourceString be the string-concatenation of prefix, " anonymous(", P, 0x000A (LINE FEED), ") {", bodyString, and "}".
  20. Set sourceString to be ? HostValidateDynamicCode(callerRealm, calleeRealm, sourceString, assembledFromCodeLike, "Function").
  21. ...

A Host Layering Points

A.1 Host-defined Fields

[[HostDefinedCodeLike]]: A string. See IsCodeLike.