Stage 3 Draft / November 27, 2024

Dynamic Code Brand Checks

1 HostGetCodeForEval ( argument )

The host-defined abstract operation HostGetCodeForEval takes argument argument (an Object) and returns a String or no-code. It allows host environments to return a String of code from argument to be used by eval, rather than eval returning argument.

argument represents the Object to be checked for code.

The default implementation of HostGetCodeForEval is to return no-code.

2 HostEnsureCanCompileStrings ( calleeRealm, parameterStrings, bodyString, direct, codeString, compilationType, parameterArgs, bodyArg )

The host-defined abstract operation HostEnsureCanCompileStrings takes arguments calleeRealm (a Realm Record), parameterStrings (a List of Strings), bodyString (a String), direct (a Boolean), codeString (a String), compilationType (direct-eval, indirect-eval, or function), parameterArgs (a List of ECMAScript language values), and bodyArg (an ECMAScript language value) and returns either a normal completion containing UNUSED or a throw completion. It allows host environments to block certain ECMAScript functions which allow developers to interpret and evaluate strings as ECMAScript code.

parameterStrings represents the strings that, when using one of the function constructors, will be concatenated together to build the parameters list. bodyString represents the function body or the string passed to an eval call. direct signifies whether the evaluation is a direct eval. codeString represents the string that will be compiled. compilationType is an enum that indicates what type of compilation this is. parameterArgs are the values passed as the leading parameters to one of the Function constructors. bodyArg is either the final parameter passed to one of the Function constructors or the value passed to an eval call.

The default implementation of HostEnsureCanCompileStrings is to return NormalCompletion(UNUSED).

3 PerformEval ( x, strictCaller, direct )

The abstract operation PerformEval takes arguments x (an ECMAScript language value), strictCaller (a Boolean), and direct (direct-eval or indirect-eval) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. Assert: If direct is indirect-eval, then strictCaller is also false.
  2. If x is a String, then
    1. Let xStr be x.
  3. Else if x is an Object, then
    1. Let code be HostGetCodeForEval(x).
    2. If code is a String, let xStr be code.
    3. Else, return x.
  4. Else,
    1. Return x.
  5. If x is not a String, return x.
  6. Let evalRealm be the current Realm Record.
  7. NOTE: In the case of a direct eval, evalRealm is the realm of both the caller of eval and of the eval function itself.
  8. Perform ? HostEnsureCanCompileStrings(evalRealm, « », x xStr, xStr, direct, « », x).
  9. Let inFunction be false.
  10. Let inMethod be false.
  11. Let inDerivedConstructor be false.
  12. Let inClassFieldInitializer be false.
  13. If direct is direct-eval, then
    1. Let thisEnvRec be GetThisEnvironment().
    2. If thisEnvRec is a Function Environment Record, then
      1. Let F be thisEnvRec.[[FunctionObject]].
      2. Set inFunction to true.
      3. Set inMethod to thisEnvRec.HasSuperBinding().
      4. If F.[[ConstructorKind]] is derived, set inDerivedConstructor to true.
      5. Let classFieldInitializerName be F.[[ClassFieldInitializerName]].
      6. If classFieldInitializerName is not empty, set inClassFieldInitializer to true.
  14. Perform the following substeps in an implementation-defined order, possibly interleaving parsing and error detection:
    1. Let script be ParseText(x xStr, Script).
  15. ...

4 CreateDynamicFunction ( constructor, newTarget, kind, parameterArgs, bodyArg )

The abstract operation CreateDynamicFunction takes arguments constructor (a constructor), newTarget (a constructor), kind (normal, generator, async, or async-generator), parameterArgs (a List of ECMAScript language values), and bodyArg (an ECMAScript language value) and returns either a normal completion containing an ECMAScript function object or a throw completion. constructor is the constructor function that is performing this action. newTarget is the constructor that new was initially applied to. parameterArgs and bodyArg reflect the argument values that were passed to constructor. It performs the following steps when called:

  1. If newTarget is undefined, set newTarget to constructor.
  2. If kind is normal, then
    1. Let prefix be "function".
    2. Let exprSym be the grammar symbol FunctionExpression.
    3. Let bodySym be the grammar symbol FunctionBody[~Yield, ~Await].
    4. Let parameterSym be the grammar symbol FormalParameters[~Yield, ~Await].
    5. Let fallbackProto be "%Function.prototype%".
  3. Else if kind is generator, then
    1. Let prefix be "function*".
    2. Let exprSym be the grammar symbol GeneratorExpression.
    3. Let bodySym be the grammar symbol GeneratorBody.
    4. Let parameterSym be the grammar symbol FormalParameters[+Yield, ~Await].
    5. Let fallbackProto be "%GeneratorFunction.prototype%".
  4. Else if kind is async, then
    1. Let prefix be "async function".
    2. Let exprSym be the grammar symbol AsyncFunctionExpression.
    3. Let bodySym be the grammar symbol AsyncFunctionBody.
    4. Let parameterSym be the grammar symbol FormalParameters[~Yield, +Await].
    5. Let fallbackProto be "%AsyncFunction.prototype%".
  5. Else,
    1. Assert: kind is async-generator.
    2. Let prefix be "async function*".
    3. Let exprSym be the grammar symbol AsyncGeneratorExpression.
    4. Let bodySym be the grammar symbol AsyncGeneratorBody.
    5. Let parameterSym be the grammar symbol FormalParameters[+Yield, +Await].
    6. Let fallbackProto be "%AsyncGeneratorFunction.prototype%".
  6. Let argCount be the number of elements in parameterArgs.
  7. Let parameterStrings be a new empty List.
  8. For each element arg of parameterArgs, do
    1. Append ? ToString(arg) to parameterStrings.
  9. Let bodyString be ? ToString(bodyArg).
  10. Let currentRealm be the current Realm Record.
  11. Perform ? HostEnsureCanCompileStrings(currentRealm, parameterStrings, bodyString, false).
  12. Let P be the empty String.
  13. If argCount > 0, then
    1. Set P to parameterStrings[0].
    2. Let k be 1.
    3. Repeat, while k < argCount,
      1. Let nextArgString be parameterStrings[k].
      2. Set P to the string-concatenation of P, "," (a comma), and nextArgString.
      3. Set k to k + 1.
  14. Let bodyParseString be the string-concatenation of 0x000A (LINE FEED), bodyString, and 0x000A (LINE FEED).
  15. Let sourceString be the string-concatenation of prefix, " anonymous(", P, 0x000A (LINE FEED), ") {", bodyParseString, and "}".
  16. Perform ? HostEnsureCanCompileStrings(currentRealm, parameterStrings, bodyString, sourceString, FUNCTION, parameterArgs, bodyArg).
  17. ...
Note

CreateDynamicFunction defines a "prototype" property on any function it creates whose kind is not async to provide for the possibility that the function will be used as a constructor.

A Host Layering Points

A.1 Host Hooks

HostGetCodeForEval(...)