示例#1
0
  private void performFunctionDeclarationBindings(
      final JSCode code, final boolean configurableBindings) {
    // 10.5 Function Declaration Binding
    List<FunctionDeclaration> decls = code.getFunctionDeclarations();

    EnvironmentRecord env = this.variableEnvironment.getRecord();
    for (FunctionDeclaration each : decls) {
      String identifier = each.getIdentifier();
      if (!env.hasBinding(this, identifier)) {
        env.createMutableBinding(this, identifier, configurableBindings);
      } else if (env.isGlobal()) {
        JSObject globalObject = ((ObjectEnvironmentRecord) env).getBindingObject();
        PropertyDescriptor existingProp =
            (PropertyDescriptor) globalObject.getProperty(this, identifier);
        if (existingProp.isConfigurable()) {
          PropertyDescriptor newProp =
              new PropertyDescriptor() {
                {
                  set("Value", Types.UNDEFINED);
                  set("Writable", true);
                  set("Enumerable", true);
                  set("Configurable", configurableBindings);
                }
              };
          globalObject.defineOwnProperty(this, identifier, newProp, true);
        } else if (existingProp.isAccessorDescriptor()
            || (!existingProp.isWritable() && !existingProp.isEnumerable())) {
          throw new ThrowException(
              this, createTypeError("unable to bind function '" + identifier + "'"));
        }
      }
      JSFunction function =
          getCompiler()
              .compileFunction(
                  this, identifier, each.getFormalParameters(), each.getBlock(), each.isStrict());
      function.setDebugContext(identifier);
      env.setMutableBinding(this, identifier, function, code.isStrict());
    }
  }
示例#2
0
  private Arguments createArgumentsObject(final JSFunction function, final Object[] arguments) {
    // 10.6

    Arguments obj = new Arguments(getGlobalObject());
    PropertyDescriptor desc =
        new PropertyDescriptor() {
          {
            set("Value", arguments.length);
            set("Writable", true);
            set("Enumerable", false);
            set("Configurable", true);
          }
        };
    obj.defineOwnProperty(this, "length", desc, false);

    String[] names = function.getFormalParameters();

    JSObject map = new DynObject(getGlobalObject());
    List<String> mappedNames = new ArrayList<>();

    final LexicalEnvironment env = getVariableEnvironment();

    for (int i = 0; i < arguments.length; ++i) {
      final Object val = arguments[i];
      desc =
          new PropertyDescriptor() {
            {
              set("Value", val);
              set("Writable", true);
              set("Enumerable", true);
              set("Configurable", true);
            }
          };

      obj.defineOwnProperty(this, "" + i, desc, false);

      if (i < names.length) {
        if (!function.isStrict()) {
          final String name = names[i];
          if (i < names.length) {
            if (!mappedNames.contains(name)) {
              mappedNames.add(name);

              desc =
                  new PropertyDescriptor() {
                    {
                      set("Set", new ArgSetter(env, name));
                      set("Get", new ArgGetter(env, name));
                      set("Configurable", true);
                    }
                  };
              map.defineOwnProperty(this, "" + i, desc, false);
            }
          }
        }
      }
    }

    if (!mappedNames.isEmpty()) {
      obj.setParameterMap(map);
    }

    if (function.isStrict()) {
      final JSFunction thrower = (JSFunction) getGlobalObject().get(this, "__throwTypeError");

      obj.defineOwnProperty(
          this,
          "caller",
          new PropertyDescriptor() {
            {
              set("Get", thrower);
              set("Set", thrower);
              set("Enumerable", false);
              set("Configurable", false);
            }
          },
          false);

      obj.defineOwnProperty(
          this,
          "callee",
          new PropertyDescriptor() {
            {
              set("Get", thrower);
              set("Set", thrower);
              set("Enumerable", false);
              set("Configurable", false);
            }
          },
          false);

    } else {
      obj.defineOwnProperty(
          this,
          "callee",
          new PropertyDescriptor() {
            {
              set("Value", function);
              set("Writable", true);
              set("Enumerable", false);
              set("Configurable", true);
            }
          },
          false);
    }

    return obj;
  }