text:
package com.google.javascript.jscomp;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.javascript.jscomp.AstFactory.type;
import static com.google.javascript.jscomp.ClosurePrimitiveErrors.INVALID_CLOSURE_CALL_SCOPE_ERROR;
import static com.google.javascript.jscomp.ClosurePrimitiveErrors.INVALID_DESTRUCTURING_FORWARD_DECLARE;
import static com.google.javascript.jscomp.ClosurePrimitiveErrors.INVALID_GET_NAMESPACE;
import static com.google.javascript.jscomp.ClosurePrimitiveErrors.INVALID_REQUIRE_NAMESPACE;
import static com.google.javascript.jscomp.ClosurePrimitiveErrors.MISSING_MODULE_OR_PROVIDE;
import static com.google.javascript.jscomp.ClosurePrimitiveErrors.MODULE_USES_GOOG_MODULE_GET;
import static com.google.javascript.jscomp.ClosureRewriteModule.ILLEGAL_MODULE_RENAMING_CONFLICT;
import static com.google.javascript.jscomp.parsing.parser.FeatureSet.Feature.MODULES;

import com.google.common.base.Splitter;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import com.google.javascript.jscomp.CompilerOptions.ChunkOutputType;
import com.google.javascript.jscomp.ModuleRenaming.GlobalizedModuleName;
import com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback;
import com.google.javascript.jscomp.deps.ModuleLoader;
import com.google.javascript.jscomp.modules.Binding;
import com.google.javascript.jscomp.modules.Module;
import com.google.javascript.jscomp.modules.ModuleMap;
import com.google.javascript.jscomp.modules.ModuleMetadataMap;
import com.google.javascript.jscomp.modules.ModuleMetadataMap.ModuleMetadata;
import com.google.javascript.jscomp.parsing.parser.FeatureSet.Feature;
import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.JSTypeExpression;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.QualifiedName;
import com.google.javascript.rhino.Token;
import com.google.javascript.rhino.jstype.JSType;
import com.google.javascript.rhino.jstype.JSTypeNative;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jspecify.nullness.Nullable;

/**
 * Rewrites a ES6 module into a form that can be safely concatenated. Note that we treat a file as
 * an ES6 module if it has at least one import or export statement.
 *
 *
Also rewrites any goog.{require,requireType,forwardDeclare,goog.module.get} calls that are
 * either in an ES module or of an ES module using goog.declareModuleId.
 */
public final class Es6RewriteModules implements CompilerPass, NodeTraversal.Callback {
  static final DiagnosticType LHS_OF_GOOG_REQUIRE_MUST_BE_CONST =
      DiagnosticType.error(
          "JSC_LHS_OF_GOOG_REQUIRE_MUST_BE_CONST",
          "The left side of a goog.require() or goog.requireType() "
              + "must use ''const'' (not ''let'' or ''var'')");

  static final DiagnosticType REQUIRE_TYPE_FOR_ES6_SHOULD_BE_CONST =
      DiagnosticType.error(
          "JSC_REQUIRE_TYPE_FOR_ES6_SHOULD_BE_CONST",
          "goog.requireType alias for ES6 module should be const.");

  static final DiagnosticType FORWARD_DECLARE_FOR_ES6_SHOULD_BE_CONST =
      DiagnosticType.error(
          "JSC_FORWARD_DECLARE_FOR_ES6_SHOULD_BE_CONST",
          "goog.forwardDeclare alias for ES6 module should be const.");

  static final DiagnosticType SHOULD_IMPORT_ES6_MODULE =
      DiagnosticType.warning(
          "JSC_SHOULD_IMPORT_ES6_MODULE",
          "ES6 modules should import other ES6 modules rather than goog.require them.");

  private final AbstractCompiler compiler;
  private final AstFactory astFactory;
  private final JSType unknownType;
  private static final Splitter DOT_SPLITTER = Splitter.on(".");

  private final @Nullable PreprocessorSymbolTable preprocessorSymbolTable;

  /**
   * Local variable names that were goog.require'd to qualified name we need to line.
   *
   *
We need to inline all required names since there are certain well-known Closure symbols
   * (like goog.asserts) that later stages of the compiler check for and cannot handle aliases.
   *
   *
We use this to rewrite something like:
   *
   *

   *   import {x} from '';
   *   const {assert} = goog.require('goog.asserts');
   *   assert(x);
   *

   *
   * To:
   *
   *

   *   import {x} from '';
   *   goog.asserts.assert(x);
   *

   *
   * Because if we used an alias like below the assertion would not be recognized:
   *
   *

   *   import {x} from '';
   *   const {assert} = goog.asserts;
   *   assert(x);
   *

   */
  // TODO(johnplaisted): This is actually incorrect if the require'd thing is mutated. But we need
  // it so that things like goog.asserts work. Mutated closure symbols are a lot rarer than needing
  // to use asserts and the like. Until there's a better solution to finding aliases of well known
  // symbols we have to inline anything that is require'd.
  private Map<String, GlobalizedModuleName> namesToInlineByAlias;

  private Set<String> typedefs;

  private final ModuleMetadataMap moduleMetadataMap;
  private final ModuleMap moduleMap;
  private final TypedScope globalTypedScope;
  private final ChunkOutputType chunkOutputType;

  /**
   * Creates a new Es6RewriteModules instance which can be used to rewrite ES6 modules to a
   * concatenable form.
   */
  Es6RewriteModules(
      AbstractCompiler compiler,
      ModuleMetadataMap moduleMetadataMap,
      ModuleMap moduleMap,
      @Nullable PreprocessorSymbolTable preprocessorSymbolTable,
      @Nullable TypedScope globalTypedScope) {
    this(
        compiler,
        moduleMetadataMap,
        moduleMap,
        preprocessorSymbolTable,
        globalTypedScope,
        ChunkOutputType.GLOBAL_NAMESPACE);
  }

  /**
   * Creates a new Es6RewriteModules instance which can be used to rewrite ES6 modules to a
   * concatenable form.
   */
  Es6RewriteModules(
      AbstractCompiler compiler,
      ModuleMetadataMap moduleMetadataMap,
      ModuleMap moduleMap,
      @Nullable PreprocessorSymbolTable preprocessorSymbolTable,
      @Nullable TypedScope globalTypedScope,
      ChunkOutputType chunkOutputType) {
    checkNotNull(moduleMetadataMap);
    this.compiler = compiler;
    this.astFactory = compiler.createAstFactory();
    this.moduleMetadataMap = moduleMetadataMap;
    this.moduleMap = moduleMap;
    this.preprocessorSymbolTable = preprocessorSymbolTable;
    this.globalTypedScope = globalTypedScope;
    this.unknownType = compiler.getTypeRegistry().getNativeType(JSTypeNative.UNKNOWN_TYPE);
    this.chunkOutputType = chunkOutputType;
  }

  /**
   * Return whether or not the given script node represents an ES6 module file.
   */
  public static boolean isEs6ModuleRoot(Node scriptNode) {
    checkArgument(scriptNode.isScript(), scriptNode);
    if (scriptNode.getBooleanProp(Node.GOOG_MODULE)) {
      return false;
    }
    return scriptNode.hasChildren() && scriptNode.getFirstChild().isModuleBody();
  }

  @Override
  public void process(Node externs, Node root) {
    checkArgument(externs.isRoot(), externs);
    checkArgument(root.isRoot(), root);
    NodeTraversal.traverseRoots(compiler, this, externs, root);
    compiler.setFeatureSet(compiler.getFeatureSet().without(MODULES));
    // This pass may add getters properties on module objects.
    GatherGetterAndSetterProperties.update(compiler, externs, root);
  }

  private void clearPerFileState() {
    this.typedefs = new HashSet<>();
    this.namesToInlineByAlias = new HashMap<>();
  }

  private static final QualifiedName GOOG_REQUIRE = QualifiedName.of("goog.require");
  private static final QualifiedName GOOG_REQUIRETYPE = QualifiedName.of("goog.requireType");
  private static final QualifiedName GOOG_MODULE_GET = QualifiedName.of("goog.module.get");
  private static final QualifiedName GOOG_FORWARDDECLARE = QualifiedName.of("goog.forwardDeclare");
  private static final QualifiedName GOOG_DECLAREMODULEID =
      QualifiedName.of("goog.declareModuleId");

  /**
   * Checks for goog.require, goog.requireType, goog.module.get and goog.forwardDeclare calls that
   * are meant to import ES6 modules and rewrites them.
   */
  private class RewriteRequiresForEs6Modules extends AbstractPostOrderCallback {
    private boolean transpiled = false;
    // An (s, old, new) entry indicates that occurrences of `old` in scope `s` should be rewritten
    // as `new`. This is used to rewrite namespaces that appear in calls to goog.requireType and
    // goog.forwardDeclare.
    private Table<Node, String, String> renameTable;

    void rewrite(Node scriptNode) {
      transpiled = false;
      renameTable = HashBasedTable.create();
      NodeTraversal.traverse(compiler, scriptNode, this);

      if (transpiled) {
        scriptNode.putBooleanProp(Node.TRANSPILED, true);
      }

      if (!renameTable.isEmpty()) {
        NodeTraversal.traverse(
            compiler, scriptNode, new Es6RenameReferences(renameTable, /* typesOnly= */ true));
      }
    }

    @Override
    public void visit(NodeTraversal t, Node n, Node parent) {
      if (!n.isCall()) {
        return;
      }

      Node callTarget = n.getFirstChild();
      if (!callTarget.isGetProp()) {
        return;
      }

      boolean isRequire = GOOG_REQUIRE.matches(callTarget);
      boolean isRequireType = GOOG_REQUIRETYPE.matches(callTarget);
      boolean isGet = GOOG_MODULE_GET.matches(callTarget);
      boolean isForwardDeclare = GOOG_FORWARDDECLARE.matches(callTarget);

      if (!isRequire && !isRequireType && !isGet && !isForwardDeclare) {
        return;
      }

      if (!n.hasTwoChildren() || !n.getLastChild().isStringLit()) {
        // Reported in CheckClosureImports, don't report here.

        return;
      }

      String name = n.getLastChild().getString();
      ModuleMetadata moduleMetadata = moduleMetadataMap.getModulesByGoogNamespace().get(name);

      if (moduleMetadata == null || !moduleMetadata.isEs6Module()) {
        return;
      }

      // TODO(johnplaisted): Once we have an alternative to forwardDeclare / requireType that
      // doesn't require Closure Library warn about those too.
      // TODO(johnplaisted): Once we have import() support warn about goog.module.get.
      if (isRequire) {
        ModuleMetadata currentModuleMetadata =
            moduleMetadataMap.getModulesByPath().get(t.getInput().getPath().toString());
        if (currentModuleMetadata != null && currentModuleMetadata.isEs6Module()) {
          t.report(n, SHOULD_IMPORT_ES6_MODULE);
        }
      }

      if (isGet && t.inGlobalHoistScope()) {
        return;
      }

      Node statementNode = NodeUtil.getEnclosingStatement(n);
      boolean importHasAlias = NodeUtil.isNameDeclaration(statementNode);
      if (importHasAlias) {
        if (statementNode.getFirstChild().isDestructuringLhs()) {
          if (isForwardDeclare) {
            // const {a, c:b} = goog.forwardDeclare('an.es6.namespace');
            t.report(n, INVALID_DESTRUCTURING_FORWARD_DECLARE);
            return;
          }
          if (isRequireType) {
            if (!statementNode.isConst()) {
              t.report(statementNode, REQUIRE_TYPE_FOR_ES6_SHOULD_BE_CONST);
              return;
            }
            // const {a, c:b} = goog.requireType('an.es6.namespace');
            for (Node child = statementNode.getFirstFirstChild().getFirstChild();
                child != null;
                child = child.getNext()) {
              checkState(child.isStringKey());
              checkState(child.getFirstChild().isName());
              renameTable.put(
                  t.getScopeRoot(),
                  child.getFirstChild().getString(),
                  ModuleRenaming.getGlobalName(moduleMetadata, name)
                      .getprop(child.getString())
                      .join());
            }
          } else {
            // Work around a bug in the type checker where destructuring can create
            // too many layers of aliases and confuse the type checker. b/112061124.

            // const {a, c:b} = goog.require('an.es6.namespace');
            // const a = module$es6.a;
            // const b = module$es6.c;
            for (Node child = statementNode.getFirstFirstChild().getFirstChild();
                child != null;
                child = child.getNext()) {
              checkState(child.isStringKey());
              checkState(child.getFirstChild().isName());
              GlobalizedModuleName globalName =
                  getGlobalNameAndType(
                          moduleMetadata, name, /* isFromMissingModuleOrProvide= */ false)
                      .getprop(child.getString());
              Node constNode =
                  astFactory.createSingleConstNameDeclaration(
                      child.getFirstChild().getString(), globalName.toQname(astFactory));
              constNode.srcrefTree(child);
              constNode.insertBefore(statementNode);
            }
          }
          statementNode.detach();
          t.reportCodeChange();
        } else {
          if (isForwardDeclare || isRequireType) {
            if (!statementNode.isConst()) {
              DiagnosticType diagnostic =
                  isForwardDeclare
                      ? FORWARD_DECLARE_FOR_ES6_SHOULD_BE_CONST
                      : REQUIRE_TYPE_FOR_ES6_SHOULD_BE_CONST;
              t.report(statementNode, diagnostic);
              return;
            }
            // const namespace = goog.forwardDeclare('an.es6.namespace');
            // const namespace = goog.requireType('an.es6.namespace');
            renameTable.put(
                t.getScopeRoot(),
                statementNode.getFirstChild().getString(),
                ModuleRenaming.getGlobalName(moduleMetadata, name).join());
            statementNode.detach();
            t.reportCodeChange();
          } else {
            // const module = goog.require('an.es6.namespace');
            // const module = module$es6;
            n.replaceWith(
                astFactory
                    .createName(
                        ModuleRenaming.getGlobalName(moduleMetadata, name).getRoot(), type(n))
                    .srcrefTree(n));
            t.reportCodeChange();
          }
        }
      } else {
        if (isForwardDeclare || isRequireType) {
          // goog.forwardDeclare('an.es6.namespace')
          // goog.requireType('an.es6.namespace')
          renameTable.put(
              t.getScopeRoot(), name, ModuleRenaming.getGlobalName(moduleMetadata, name).join());
          statementNode.detach();
        } else {
          // goog.require('an.es6.namespace')
          if (statementNode.isExprResult() && statementNode.getFirstChild() == n) {
            statementNode.detach();
          } else {
            n.replaceWith(
                astFactory
                    .createName(
                        ModuleRenaming.getGlobalName(moduleMetadata, name).getRoot(), type(n))
                    .srcrefTree(n));
          }
        }
        t.reportCodeChange();
      }

      transpiled = true;
    }
  }

  @Override
  public boolean shouldTraverse(NodeTraversal nodeTraversal, Node n, Node parent) {
    if (n.isScript()) {
      // Trigger creation of the global scope before inserting any synthetic code.
      nodeTraversal.getScope();
      new RewriteRequiresForEs6Modules().rewrite(n);
      if (isEs6ModuleRoot(n)) {
        clearPerFileState();
        n.putBooleanProp(Node.TRANSPILED, true);
      } else {
        return false;
      }
    }
    return true;
  }

  @Override
  public void visit(NodeTraversal t, Node n, Node parent) {
    if (n.isImport()) {
      maybeWarnExternModule(t, n, parent);
      visitImport(t, n, parent);
    } else if (n.isExport()) {
      maybeWarnExternModule(t, n, parent);
      visitExport(t, n, parent);
    } else if (n.isScript()) {
      visitScript(t, n);
    } else if (n.isCall()) {
      if (GOOG_DECLAREMODULEID.matches(n.getFirstChild())) {
        n.getParent().detach();
      }
    } else if (n.isImportMeta()) {
      if (chunkOutputType != ChunkOutputType.ES_MODULES) {
        // Since import.meta cannot be transpiled, we are only supporting it when the output format
        // is a module. The default output format type is just script.
        t.report(
            n,
            TranspilationUtil.CANNOT_CONVERT,
            "import.meta. Use --chunk_output_type=ES_MODULES to allow passthrough support.");
      }
    }
  }

  private void maybeWarnExternModule(NodeTraversal t, Node n, Node parent) {
    checkState(parent.isModuleBody());
    if (parent.isFromExterns() && !NodeUtil.isFromTypeSummary(parent.getParent())) {
      t.report(n, TranspilationUtil.CANNOT_CONVERT_YET, "ES6 modules in externs");
    }
  }

  private void visitImport(NodeTraversal t, Node importDecl, Node parent) {
    checkArgument(parent.isModuleBody(), parent);
    String importName = importDecl.getLastChild().getString();
    boolean isNamespaceImport = importName.startsWith("goog:");
    if (isNamespaceImport) {
      // Allow importing Closure namespace objects (e.g. from goog.provide or goog.module) as
      //   import ... from 'goog:my.ns.Object'.
      String namespace = importName.substring("goog:".length());
      ModuleMetadata m = moduleMetadataMap.getModulesByGoogNamespace().get(namespace);

      if (m == null) {
        t.report(importDecl, MISSING_MODULE_OR_PROVIDE, namespace);
      } else {
        checkState(m.isEs6Module() || m.isGoogModule() || m.isGoogProvide());
      }
    } else {
      ModuleLoader.ModulePath modulePath =
          t.getInput()
              .getPath()
              .resolveJsModule(
                  importName,
                  importDecl.getSourceFileName(),
                  importDecl.getLineno(),
                  importDecl.getCharno());
      if (modulePath == null) {
        // The module loader issues an error
        // Fall back to assuming the module is a file path
        modulePath = t.getInput().getPath().resolveModuleAsPath(importName);
      }

      maybeAddImportedFileReferenceToSymbolTable(importDecl.getLastChild(), modulePath.toString());
      // TODO(johnplaisted): Use ModuleMetadata to ensure the path required is CommonJs or ES6 and
      // if not give a better error.
    }

    for (Node child = importDecl.getFirstChild(); child != null; child = child.getNext()) {
      if (child.isImportSpecs()) {
        for (Node grandChild = child.getFirstChild();
            grandChild != null;
            grandChild = grandChild.getNext()) {
          maybeAddAliasToSymbolTable(grandChild.getFirstChild(), t.getSourceName());
          checkState(grandChild.hasTwoChildren());
        }
      } else if (child.isImportStar()) {
        // import * as ns from "mod"
        maybeAddAliasToSymbolTable(child, t.getSourceName());
      }
    }

    importDecl.detach();
    t.reportCodeChange();
  }

  private void visitExport(NodeTraversal t, Node export, Node parent) {
    checkArgument(parent.isModuleBody(), parent);
    if (export.getBooleanProp(Node.EXPORT_DEFAULT)) {
      // export default

      // If the thing being exported is a class or function that has a name,
      // extract it from the export statement, so that it can be referenced
      // from within the module.
      //
      //   export default class X {} -> class X {}; ... moduleName.default = X;
      //   export default function X() {} -> function X() {}; ... moduleName.default = X;
      //
      // Otherwise, create a local variable for it and export that.
      //
      //   export default 'someExpression'
      //     ->
      //   var $jscompDefaultExport = 'someExpression';
      //   ...
      //   moduleName.default = $jscompDefaultExport;
      Node child = export.getFirstChild();
      String name = null;

      if (child.isFunction() || child.isClass()) {
        name = NodeUtil.getName(child);
      }

      if (name != null) {
        Node decl = child.detach();
        export.replaceWith(decl);
      } else {
        Node var =
            astFactory.createSingleVarNameDeclaration(
                ModuleRenaming.DEFAULT_EXPORT_VAR_PREFIX, export.removeFirstChild());
        var.setJSDocInfo(child.getJSDocInfo());
        child.setJSDocInfo(null);
        var.srcrefTreeIfMissing(export);
        export.replaceWith(var);
      }
      t.reportCodeChange();
    } else if (export.getBooleanProp(Node.EXPORT_ALL_FROM)
        || export.hasTwoChildren()
        || export.getFirstChild().isExportSpecs()) {
      //   export * from 'moduleIdentifier';
      //   export {x, y as z} from 'moduleIdentifier';
      //   export {Foo};
      export.detach();
      t.reportCodeChange();
    } else {
      visitExportDeclaration(t, export);
    }
  }

  private void visitExportNameDeclaration(Node declaration) {
    if (declaration.getJSDocInfo() != null && declaration.getJSDocInfo().hasTypedefType()) {
      //    export var Foo;
      //    export let {a, b:[c,d]} = {};
      NodeUtil.visitLhsNodesInNode(declaration, (lhs) -> typedefs.add(lhs.getString()));
    }
  }

  private void visitExportDeclaration(NodeTraversal t, Node export) {
    //    export var Foo;
    //    export function Foo() {}
    // etc.
    Node declaration = export.getFirstChild();

    if (NodeUtil.isNameDeclaration(declaration)) {
      visitExportNameDeclaration(declaration);
    }

    export.replaceWith(declaration.detach());
    t.reportCodeChange();
  }

  private void inlineModuleToGlobalScope(Node moduleNode) {
    checkState(moduleNode.isModuleBody());
    Node scriptNode = moduleNode.getParent();
    moduleNode.detach();
    scriptNode.addChildrenToFront(moduleNode.removeChildren());
  }

  private void visitScript(NodeTraversal t, Node script) {
    final Node moduleBody = script.getFirstChild();
    // TypedScopeCreator sets the module object type on the MODULE_BODY during type checking.
    final AstFactory.Type moduleObjectType = type(moduleBody);
    inlineModuleToGlobalScope(moduleBody);

    ClosureRewriteModule.checkAndSetStrictModeDirective(t, script);

    Module thisModule = moduleMap.getModule(t.getInput().getPath());
    QualifiedName qualifiedName =
        ModuleRenaming.getGlobalName(thisModule.metadata(), /* googNamespace= */ null);
    checkState(qualifiedName.isSimple(), "Unexpected qualified name %s", qualifiedName);
    String moduleName = qualifiedName.getRoot();

    Node moduleVar = createExportsObject(moduleName, t, script, moduleObjectType);

    // Rename vars to not conflict in global scope.
    NodeTraversal.traverse(compiler, script, new RenameGlobalVars(thisModule));

    // Rename the exports object to something we can reference later.
    moduleVar.getFirstChild().setString(moduleName);
    moduleVar.makeNonIndexableRecursive();
    declareGlobalVariable(moduleVar.getFirstChild(), t);

    // rewriteRequires is here (rather than being part of the main visit() method, because we only
    // want to rewrite the requires if this is an ES6 module. Note that we also want to do this
    // AFTER renaming all module scoped vars in the event that something that is goog.require'd is
    // a global, unqualified name (e.g. if "goog.provide('foo')" exists, we don't want to rewrite
    // "const foo = goog.require('foo')" to "const foo = foo". If we rewrite our module scoped names
    // first then we'll rewrite to "const foo$module$fudge = goog.require('foo')", then to
    // "const foo$module$fudge = foo".
    rewriteRequires(script);

    t.reportCodeChange();
  }

  private Node createExportsObject(
      String moduleName, NodeTraversal t, Node script, AstFactory.Type moduleObjectType) {
    Node moduleObject = astFactory.createObjectLit(moduleObjectType);
    // Going to get renamed by RenameGlobalVars, so the name we choose here doesn't matter as long
    // as it doesn't collide with an existing variable. (We can't use `moduleName` since then
    // RenameGlobalVars will rename all references to `moduleName` incorrectly). We'll fix the name
    // in visitScript after the global renaming to ensure it has a name that is deterministic from
    // the path.
    //
    // So after this method we'll have:
    // var $jscomp$tmp$exports$module$name = {};
    // module$name.exportName = localName;
    //
    // After RenameGlobalVars:
    // var $jscomp$tmp$exports$module$nameglobalized = {};
    // module$name.exportName = localName$globalized;
    //
    // After visitScript:
    // var module$name = {};
    // module$name.exportName = localName$globalized;
    Node moduleVar =
        astFactory.createSingleVarNameDeclaration("$jscomp$tmp$exports$module$name", moduleObject);
    moduleVar.getFirstChild().putBooleanProp(Node.MODULE_EXPORT, true);
    // TODO(b/144593112): Stop adding JSDoc when this pass moves to always be after typechecking.
    JSDocInfo.Builder infoBuilder = JSDocInfo.builder();
    infoBuilder.recordConstancy();
    moduleVar.setJSDocInfo(infoBuilder.build());
    moduleVar.getFirstChild().setDeclaredConstantVar(true);
    script.addChildToBack(moduleVar.srcrefTreeIfMissing(script));

    Module thisModule = moduleMap.getModule(t.getInput().getPath());

    for (Map.Entry<String, Binding> entry : thisModule.namespace().entrySet()) {
      String exportedName = entry.getKey();
      Binding binding = entry.getValue();
      Node nodeForSourceInfo = binding.sourceNode();
      boolean mutated = binding.isMutated();
      QualifiedName boundVariableQualifiedName = ModuleRenaming.getGlobalName(binding);
      checkState(
          boundVariableQualifiedName.isSimple(),
          "unexpected qualified name: %s",
          boundVariableQualifiedName);
      String boundVariableName = boundVariableQualifiedName.getRoot();

      Node getProp =
          astFactory.createGetPropWithoutColor(
              astFactory.createName(moduleName, moduleObjectType), exportedName);
      getProp.putBooleanProp(Node.MODULE_EXPORT, true);

      if (typedefs.contains(exportedName)) {
        // /** @typedef {foo} */
        // moduleName.foo;
        JSDocInfo.Builder builder = JSDocInfo.builder().parseDocumentation();
        JSTypeExpression typeExpr =
            new JSTypeExpression(
                astFactory.createString(exportedName).srcref(nodeForSourceInfo),
                script.getSourceFileName());
        builder.recordTypedef(typeExpr);
        JSDocInfo info = builder.build();
        getProp.setJSDocInfo(info);
        Node exprResult = astFactory.exprResult(getProp).srcrefTreeIfMissing(nodeForSourceInfo);
        script.addChildToBack(exprResult);
      } else if (mutated) {
        final Node globalExportName = astFactory.createName(boundVariableName, type(getProp));
        addGetterExport(script, nodeForSourceInfo, moduleObject, exportedName, globalExportName);
        NodeUtil.addFeatureToScript(t.getCurrentScript(), Feature.GETTER, compiler);
      } else {
        // Avoid the extra complexity of using getters when the property isn't mutated.
        // exports.foo = foo;
        Node assign =
            astFactory.createAssign(
                getProp, astFactory.createName(boundVariableName, type(getProp)));
        // TODO(b/144593112): Stop adding JSDoc when this pass moves to always be after typechecking
        JSDocInfo.Builder builder = JSDocInfo.builder().parseDocumentation();
        builder.recordConstancy();
        JSDocInfo info = builder.build();
        assign.setJSDocInfo(info);
        script.addChildToBack(astFactory.exprResult(assign).srcrefTreeIfMissing(nodeForSourceInfo));
      }
    }

    return moduleVar;
  }

  private void addGetterExport(
      Node script, Node forSourceInfo, Node objLit, String exportedName, Node value) {
    Node getter = astFactory.createGetterDef(exportedName, value);
    getter.putBooleanProp(Node.MODULE_EXPORT, true);
    objLit.addChildToBack(getter);

    if (!astFactory.isAddingTypes()) {
      // TODO(b/143904518): Remove this code when this pass is permanently moved after type checking
      // Type checker doesn't infer getters so mark the return as unknown.
      // { /** @return {?} */ get foo() { return foo; } }
      JSDocInfo.Builder builder = JSDocInfo.builder().parseDocumentation();
      builder.recordReturnType(
          new JSTypeExpression(
              new Node(Token.QMARK).srcref(forSourceInfo), script.getSourceFileName()));
      getter.setJSDocInfo(builder.build());
    } else {
      // For a property typed as number, synthesize a type `function(): number`.
      getter.setJSType(compiler.getTypeRegistry().createFunctionType(value.getJSType()));
    }

    getter.srcrefTreeIfMissing(forSourceInfo);
    compiler.reportChangeToEnclosingScope(getter.getFirstChild().getLastChild());
    compiler.reportChangeToEnclosingScope(getter);
  }

  private void rewriteRequires(Node script) {
    NodeTraversal.builder()
        .setCompiler(compiler)
        .setCallback(
            (NodeTraversal t, Node n, Node parent) -> {
              if (n.isCall()) {
                Node fn = n.getFirstChild();
                if (GOOG_REQUIRE.matches(fn) || GOOG_REQUIRETYPE.matches(fn)) {
                  // TODO(tjgq): This will rewrite both type references and code references. For
                  // goog.requireType, the latter are potentially broken because the symbols aren't
                  // guaranteed to be available at run time. A separate pass needs to be added to
                  // detect these incorrect uses of goog.requireType.
                  visitRequireOrGet(t, n, parent, /* isRequire= */ true);
                } else if (GOOG_MODULE_GET.matches(fn)) {
                  visitGoogModuleGet(t, n, parent);
                }
              }
            })
        .traverse(script);
    NodeTraversal.builder()
        .setCompiler(compiler)
        .setCallback(
            (NodeTraversal t, Node n, Node parent) -> {
              JSDocInfo info = n.getJSDocInfo();
              if (info != null) {
                for (Node typeNode : info.getTypeNodes()) {
                  inlineAliasedTypes(t, typeNode);
                }
              }

              if (n.isName() && namesToInlineByAlias.containsKey(n.getString())) {
                Var v = t.getScope().getVar(n.getString());
                if (v == null || v.getNameNode() != n) {
                  GlobalizedModuleName replacementName = namesToInlineByAlias.get(n.getString());
                  Node replacement = replacementName.toQname(astFactory).srcrefTree(n);
                  n.replaceWith(replacement);
                }
              }
            })
        .traverse(script);
  }

  private void inlineAliasedTypes(NodeTraversal t, Node typeNode) {
    if (typeNode.isStringLit()) {
      String name = typeNode.getString();
      List<String> split = DOT_SPLITTER.limit(2).splitToList(name);

      // We've already removed the alias.
      if (t.getScope().getVar(split.get(0)) == null) {
        GlobalizedModuleName replacement = namesToInlineByAlias.get(split.get(0));
        if (replacement != null) {
          String rest = "";
          if (split.size() == 2) {
            rest = "." + split.get(1);
          }
          typeNode.setOriginalName(name);
          typeNode.setString(replacement.aliasName().join() + rest);
          t.reportCodeChange();
        }
      }
    }
    for (Node child = typeNode.getFirstChild(); child != null; child = child.getNext()) {
      inlineAliasedTypes(t, child);
    }
  }

  private void visitGoogModuleGet(NodeTraversal t, Node getCall, Node parent) {
    if (!getCall.hasTwoChildren() || !getCall.getLastChild().isStringLit()) {
      t.report(getCall, INVALID_GET_NAMESPACE);
      return;
    }

    // Module has already been turned into a script at this point.
    if (t.inGlobalHoistScope()) {
      t.report(getCall, MODULE_USES_GOOG_MODULE_GET);
      return;
    }

    visitRequireOrGet(t, getCall, parent, /* isRequire= */ false);
  }

  /**
   * Gets some made-up metadata for the given Closure namespace.
   *
   *
This is used when the namespace is not part of the input so that this pass can be fault
   * tolerant and still rewrite to something. Some tools don't care about rewriting correctly and
   * just want the type information of this module (e.g. clutz).
   */
  private ModuleMetadata getFallbackMetadataForNamespace(String namespace) {
    // Assume a provide'd file to be consistent with goog.module rewriting.
    ModuleMetadata.Builder builder =
        ModuleMetadata.builder()
            .moduleType(ModuleMetadataMap.ModuleType.GOOG_PROVIDE)
            .usesClosure(true)
            .isTestOnly(false);
    builder.googNamespacesBuilder().add(namespace);
    return builder.build();
  }

  private void visitRequireOrGet(
      NodeTraversal t, Node requireCall, Node parent, boolean isRequire) {
    if (!requireCall.hasTwoChildren() || !requireCall.getLastChild().isStringLit()) {
      t.report(requireCall, INVALID_REQUIRE_NAMESPACE);
      return;
    }

    // Module has already been turned into a script at this point.
    if (isRequire && !t.getScope().isGlobal()) {
      t.report(requireCall, INVALID_CLOSURE_CALL_SCOPE_ERROR);
      return;
    }

    String namespace = requireCall.getLastChild().getString();

    boolean isStoredInDeclaration = NodeUtil.isDeclaration(parent.getParent());

    if (isStoredInDeclaration && !parent.getParent().isConst()) {
      compiler.report(JSError.make(parent.getParent(), LHS_OF_GOOG_REQUIRE_MUST_BE_CONST));
    }

    ModuleMetadata m = moduleMetadataMap.getModulesByGoogNamespace().get(namespace);

    boolean isFromFallbackMetadata = m == null;
    if (isFromFallbackMetadata) {
      t.report(requireCall, MISSING_MODULE_OR_PROVIDE, namespace);
      m = getFallbackMetadataForNamespace(namespace);
    }

    if (isStoredInDeclaration) {
      if (isRequire) {
        Node toDetach;

        if (parent.isDestructuringLhs()) {
          checkState(parent.getFirstChild().isObjectPattern());
          toDetach = parent.getParent();
          for (Node child = parent.getFirstFirstChild(); child != null; child = child.getNext()) {
            checkState(child.isStringKey() && child.getFirstChild().isName(), child);
            GlobalizedModuleName rep =
                getGlobalNameAndType(m, namespace, isFromFallbackMetadata)
                    .getprop(child.getString());
            namesToInlineByAlias.put(child.getFirstChild().getString(), rep);
          }
        } else if (parent.isName()) {
          GlobalizedModuleName alias = getGlobalNameAndType(m, namespace, isFromFallbackMetadata);
          namesToInlineByAlias.put(parent.getString(), alias);

          toDetach = parent.getParent();
        } else {
          checkState(parent.isExprResult());
          toDetach = parent;
        }
        toDetach.detach();
      } else {
        GlobalizedModuleName name = getGlobalNameAndType(m, namespace, isFromFallbackMetadata);
        Node replacement = name.toQname(astFactory).srcrefTree(requireCall);
        requireCall.replaceWith(replacement);
      }
    } else {
      checkState(requireCall.getParent().isExprResult());
      requireCall.getParent().detach();
    }
  }

  /**
   * Looks up information about the globalized name and type of a given module
   *
   * @param metadata Required. The metadata for the module or provide being imported.
   * @param googNamespace Optional.
   * @param isFromMissingModuleOrProvide Whether the metadata is synthesized fallback metadata
   */
  private GlobalizedModuleName getGlobalNameAndType(
      ModuleMetadata metadata,
      @Nullable String googNamespace,
      boolean isFromMissingModuleOrProvide) {
    if (isFromMissingModuleOrProvide) {
      // The missing namespace presumably does not have a corresponding type defined in the scope.
      // Use the unknownType instead of asking ModuleRenaming to look up the type.
      QualifiedName globalName = ModuleRenaming.getGlobalName(metadata, googNamespace);
      return GlobalizedModuleName.create(globalName, unknownType);
    }
    return GlobalizedModuleName.create(metadata, googNamespace, globalTypedScope);
  }

  /**
   * Traverses a node tree and
   *
   *

   *
Appends a suffix to all global variable names defined in this module.
   *
Changes references to imported values to access the exported variable.
   *

   */
  private class RenameGlobalVars extends AbstractPostOrderCallback {
    private final Module thisModule;

    RenameGlobalVars(Module thisModule) {
      this.thisModule = thisModule;
    }

    @Override
    public void visit(NodeTraversal t, Node n, Node parent) {
      JSDocInfo info = n.getJSDocInfo();
      if (info != null) {
        for (Node typeNode : info.getTypeNodes()) {
          fixTypeNode(t, typeNode);
        }
      }

      if (n.isName()) {
        String name = n.getString();

        Var var = t.getScope().getVar(name);
        if (var != null && var.isGlobal()) {
          // Avoid polluting the global namespace.
          String newName =
              ModuleRenaming.getGlobalNameOfEsModuleLocalVariable(thisModule.metadata(), name)
                  .join();
          n.setString(newName);
          n.setOriginalName(name);
          t.reportCodeChange(n);
          if (NodeUtil.isDeclarationLValue(n)) {
            declareGlobalVariable(n, t);
          }
        } else if (var == null && thisModule.boundNames().containsKey(name)) {
          // Imports have been detached, so they won't show up in scope. Thus if we have a variable
          // not in scope that shares the name of an import it is the import.
          maybeAddAliasToSymbolTable(n, t.getSourceName());
          Binding binding = thisModule.boundNames().get(name);

          Node replacement = replace(n, binding);

          // `n.x()` may become `foo()`
          if (replacement.isName()
              && parent.isCall()
              && parent.getFirstChild() == n
              && parent.getBooleanProp(Node.FREE_CALL)) {
            parent.putBooleanProp(Node.FREE_CALL, true);
          }

          if (NodeUtil.isDeclarationLValue(n)) {
            declareGlobalVariable(n, t);
          }
          t.reportCodeChange();
        }
      }
    }

    /**
     * Replaces the reference to a given binding. See {@link
     * ModuleRenaming#getGlobalNameForJsDoc(ModuleMap, Binding, List)} for a JS Doc version.
     *
     *
For example:
     *
     *

     *   // bar
     *   export let baz = {qux: 0};
     *

     *
     *

     *   // foo
     *   import * as bar from 'bar';
     *   export {bar};
     *

     *
     *

     *   import * as foo from 'foo';
     *   use(foo.bar.baz.qux);
     *

     *
     *
Should call this method with the binding and node for {@code foo}. In this example any of
     * these properties could also be modules. This method will replace as much as the GETPROP as it
     * can with module exported variables. Meaning in the above example this would return something
     * like "baz$$module$bar.qux", whereas if this method were called for just "foo.bar" it would
     * return "module$bar", as it refers to a module object itself.
     *
     * @param n the node to replace
     * @param binding the binding nameNode is a reference to
     */
    private Node replace(Node n, Binding binding) {
      checkState(n.isName());

      while (binding.isModuleNamespace()
          && binding.metadata().isEs6Module()
          && n.getParent().isGetProp()) {
        String propertyName = n.getParent().getString();
        Module m = moduleMap.getModule(binding.metadata().path());
        if (m.namespace().containsKey(propertyName)) {
          binding = m.namespace().get(propertyName);
          n = n.getParent();
        } else {
          // This means someone referenced an invalid export on a module object. This should be an
          // error, so just rewrite and let the type checker complain later. It isn't a super clear
          // error, but we're working on type checking modules soon.
          break;
        }
      }

      QualifiedName globalName = ModuleRenaming.getGlobalName(binding);
      final Node newNode;
      if (!globalName.isSimple()) {
        String root = globalName.getRoot();
        newNode =
            // we might encounter a name not in the global scope when requiring a missing symbol.
            globalTypedScope != null && globalTypedScope.hasSlot(root)
                ? astFactory.createQName(globalTypedScope, globalName.join())
                : astFactory.createQNameWithUnknownType(globalName.join());
      } else {
        // Because this pass does not update the global scope with injected names, t.getScope()
        // will not contain a declaration for this global name. Fortunately, we already have the
        // JSType on the existing node to pass to AstFactory.
        newNode = astFactory.createName(globalName.getRoot(), type(n));
      }

      // For kythe: the new node only represents the last name it replaced, not all the names.
      // e.g. if we rewrite `a.b.c.d.e` to `x.d.e`, then `x` should map to `c`, not `a.b.c`.
      n.replaceWith(newNode);
      newNode.srcrefTree(n);
      newNode.setOriginalName(n.getString());
      return newNode;
    }

    /**
     * Replace type name references. Change short names to fully qualified names with namespace
     * prefixes. Eg: {Foo} becomes {module$test.Foo}.
     */
    private void fixTypeNode(NodeTraversal t, Node typeNode) {
      if (typeNode.isStringLit()) {
        Module thisModule = moduleMap.getModule(t.getInput().getPath());
        String name = typeNode.getString();
        List<String> splitted = DOT_SPLITTER.splitToList(name);
        String baseName = splitted.get(0);
        String rest = "";
        if (splitted.size() > 1) {
          rest = name.substring(baseName.length());
        }
        Var var = t.getScope().getVar(baseName);
        if (var != null && var.isGlobal()) {
          maybeSetNewName(
              t,
              typeNode,
              name,
              ModuleRenaming.getGlobalNameOfEsModuleLocalVariable(thisModule.metadata(), baseName)
                      .join()
                  + rest);
        } else if (var == null && thisModule.boundNames().containsKey(baseName)) {
          // Imports have been detached, so they won't show up in scope. Thus if we have a variable
          // not in scope that shares the name of an import it is the import.
          Binding binding = thisModule.boundNames().get(baseName);
          String globalName =
              ModuleRenaming.getGlobalNameForJsDoc(
                  moduleMap, binding, splitted.subList(1, splitted.size()));
          maybeSetNewName(t, typeNode, name, globalName);

          if (preprocessorSymbolTable != null) {
            // Jsdoc type node is a single STRING node that spans the whole type. For example
            // STRING node "bar.Foo". ES6 import rewrite replaces only "module"
            // part of the type: "bar.Foo" => "module$full$path$bar$Foo". We have to record
            // "bar" as alias.
            Node onlyBaseName = Node.newString(baseName).srcref(typeNode);
            onlyBaseName.setLength(baseName.length());
            maybeAddAliasToSymbolTable(onlyBaseName, t.getSourceName());
          }
        }

        typeNode.setOriginalName(name);
      }

      for (Node child = typeNode.getFirstChild(); child != null; child = child.getNext()) {
        fixTypeNode(t, child);
      }
    }

    private void maybeSetNewName(NodeTraversal t, Node node, String name, String newName) {
      if (!name.equals(newName)) {
        node.setString(newName);
        node.setOriginalName(name);
        t.reportCodeChange();
      }
    }
  }

  /**
   * Add alias nodes to the symbol table as they going to be removed by rewriter. Example aliases:
   *
   *

   *   import * as foo from './foo';
   *   import {doBar} from './bar';
   *
   *   console.log(doBar);
   *

   *
   * @param n Alias node. In the example above alias nodes are foo, doBar, and doBar.
   * @param module Name of the module currently being processed.
   */
  private void maybeAddAliasToSymbolTable(Node n, String module) {
    if (preprocessorSymbolTable == null) {
      return;
    }
    n.putBooleanProp(Node.MODULE_ALIAS, true);
    // Alias can be used in js types. Types have node type STRING and not NAME so we have to
    // use their name as string.
    String nodeName =
        n.isStringLit() || n.isImportStar()
            ? n.getString()
            : preprocessorSymbolTable.getQualifiedName(n);
    // We need to include module as part of the name because aliases are local to current module.
    // Aliases with the same name from different module should be completely different entities.
    String name = "alias_" + module + "_" + nodeName;
    preprocessorSymbolTable.addReference(n, name);
  }

  /**
   * Add reference to a file that current module imports. Example:
   *
   *

   * import * as qux from '../some/file.js';
   *

   *
   *
Will add a reference to file.js on the string node `'../some/file.js'`.
   *
   * @param importStringNode String node from the import statement that references imported file. In
   *     the example above it is the '../some/file.js' STRING node.
   * @param importedFilePath Absolute path to the imported file. In the example above it can be
   *     myproject/folder/some/file.js
   */
  private void maybeAddImportedFileReferenceToSymbolTable(
      Node importStringNode, String importedFilePath) {
    if (preprocessorSymbolTable == null) {
      return;
    }

    // If this if the first import that mentions importedFilePath then we need to create a SCRIPT
    // node for the imported file.
    if (preprocessorSymbolTable.getSlot(importedFilePath) == null) {
      Node scriptNode = compiler.getScriptNode(importedFilePath);
      if (scriptNode != null) {
        preprocessorSymbolTable.addReference(scriptNode, importedFilePath);
      }
    }

    preprocessorSymbolTable.addReference(importStringNode, importedFilePath);
  }

  private void declareGlobalVariable(Node n, NodeTraversal t) {
    checkState(n.isName());
    if (!astFactory.isAddingTypes()) {
      return;
    }
    checkNotNull(this.globalTypedScope);

    String name = n.getString();
    if (this.globalTypedScope.hasOwnSlot(name)) {
      t.report(t.getCurrentScript(), ILLEGAL_MODULE_RENAMING_CONFLICT, name);
    } else {
      JSType type = checkNotNull(n.getJSType());
      this.globalTypedScope.declare(name, n, type, t.getInput(), false);
    }
  }
}


text:
"""
 SlipStream Client
 =====
 Copyright (C) 2014 SixSq Sarl (sixsq.com)
 =====
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
"""

import slipstream.util as util

from slipstream.NodeDecorator import NodeDecorator

def as_list(func):
    def wfun(self):
        val = func(self)
        if val:
            if isinstance(val, list):
                return map(lambda x: x.strip(), val)
            else:
                return map(lambda x: x.strip(), val.split(','))
        else:
            return []
    return wfun

class NodeInstance(object):

    IMAGE_ATTRIBUTE_PREFIX = 'image'
    IMAGE_TARGETS_PREFIX = IMAGE_ATTRIBUTE_PREFIX + '.targets'

    def __init__(self, runtime_parameters={}):
        self.__parameters = runtime_parameters

    def __str__(self):
        return 'NodeInstance(%s)' % self.__parameters

    def __repr__(self):
        return self.__str__()

    def __get(self, parameter_name, default_value=None):
        parameter = self.__parameters.get(parameter_name, default_value)
        # If the parameter exist but is None, we return the default value
        if parameter is None:
            parameter = default_value
        return parameter

    def __set(self, parameter_name, value):
        if isinstance(value, basestring):
            value = value.strip()
        self.__parameters[parameter_name] = value

    def get_cloud(self):
        return self.__get(NodeDecorator.CLOUDSERVICE_KEY)

    def get_image_attribute(self, attribute_name, default_value=None):
        return self.__get('%s.%s' %
                          (self.IMAGE_ATTRIBUTE_PREFIX, attribute_name),
                          default_value)

    def get_image_target(self, target_name, default_value=None):
        return self.__get('%s.%s' %
                          (self.IMAGE_TARGETS_PREFIX, target_name),
                          default_value)

    def get_cloud_parameter(self, parameter_name, default_value=None):
        return self.__get('%s.%s' % (self.get_cloud(), parameter_name),
                          default_value)

    def set_attributes(self, attributes):
        """attributes: dict
        """
        for key, value in attributes.items():
            self.__set(key, value)

    def set_image_attributes(self, image_attributes):
        """image_attributes: dict
        """
        for key, value in image_attributes.items():
            self.__set('%s.%s' % (self.IMAGE_ATTRIBUTE_PREFIX, key), value)

    def set_image_targets(self, image_targets):
        """image_targets: dict
        """
        for key, value in image_targets.items():
            self.__set('%s.%s' % (self.IMAGE_TARGETS_PREFIX, key), value)

    def set_build_state(self, build_state):
        self.__set(NodeDecorator.BUILD_STATE_KEY, build_state)

    def set_cloud_parameters(self, cloud_parameters):
        for key, value in cloud_parameters.items():
            self.__set('%s.%s' % (self.get_cloud(), key), value)

    def set_parameter(self, name, value):
        self.__set(name, value)

    def is_orchestrator(self):
        is_orch = self.__get(NodeDecorator.IS_ORCHESTRATOR_KEY)

        if is_orch is None:
            return NodeDecorator.is_orchestrator_name(self.get_name())
        else:
            return util.str2bool(is_orch)

    def is_windows(self):
        return self.get_platform().lower() == 'windows'

    def get_build_state(self):
        return self.__get(NodeDecorator.BUILD_STATE_KEY, {})

    def get_instance_id(self):
        return self.__get(NodeDecorator.INSTANCEID_KEY)

    def set_instance_id(self, id):
        return self.__set(NodeDecorator.INSTANCEID_KEY, id)

    def get_image_id(self):
        return self.get_image_attribute('id')

    def get_id(self):
        return self.__get('id')

    def get_image_resource_uri(self):
        return self.get_image_attribute('resourceUri')

    def get_image_short_name(self):
        return self.get_image_attribute('shortName')

    def get_image_name(self):
        return self.get_image_attribute('name')

    def get_image_version(self):
        return self.get_image_attribute('version')

    def get_image_description(self, default_value=None):
        return self.get_image_attribute('description', default_value)

    def get_volatile_extra_disk_size(self):
        return self.__get('extra.disk.volatile')

    def get_name(self):
        return self.__get(NodeDecorator.NODE_INSTANCE_NAME_KEY)

    def get_node_name(self):
        return self.__get(NodeDecorator.NODE_NAME_KEY) or self.get_name()

    def get_root_disk_size(self, default_value=None):
        return self.__get('disk.GB', default_value)

    def get_network_type(self, default_value=None):
        return self.__get('network', default_value)

    @as_list
    def get_networks(self):
        "Return list of user provided network names, or an empty list instead."
        return self.get_cloud_parameter('networks', [])

    def get_platform(self):
        return self.get_image_attribute(NodeDecorator.PLATFORM_KEY, 'linux')

    def get_scale_state(self):
        return self.__parameters.get(NodeDecorator.SCALE_STATE_KEY)

    def get_prerecipe(self):
        return self.get_image_target(NodeDecorator.NODE_PRERECIPE)

    def get_recipe(self):
        return self.get_image_target(NodeDecorator.NODE_RECIPE)

    def get_packages(self):
        return self.get_image_target(NodeDecorator.NODE_PACKAGES, [])

    def get_username(self, default_value=None):
        return self.get_image_attribute(NodeDecorator.LOGIN_USER_KEY, default_value)

    def get_password(self):
        return self.get_cloud_parameter(NodeDecorator.LOGIN_PASS_KEY)

    def get_instance_type(self):
        return self.get_cloud_parameter('instance.type')

    @as_list
    def get_security_groups(self):
        "Return list of security group names, or an empty list instead."
        return self.get_cloud_parameter(NodeDecorator.SECURITY_GROUPS_KEY, [])

    def get_cpu(self):
        return self.get_cloud_parameter('cpu')

    def get_ram(self):
        return self.get_cloud_parameter('ram')

    def get_smp(self):
        return self.get_cloud_parameter('smp')

    def get_max_provisioning_failures(self):
        return self.__get(NodeDecorator.MAX_PROVISIONING_FAILURES_KEY)

    def get_disk_attach_size(self):
        return self.__get(NodeDecorator.SCALE_DISK_ATTACH_SIZE)

    def get_disk_detach_device(self):
        return self.__get(NodeDecorator.SCALE_DISK_DETACH_DEVICE)

    def set_deployment_context(self, context=None):
        self.__set(NodeDecorator.DEPLOYMENT_CONTEXT_KEY, context)

    def get_deployment_context(self):
        return self.__get(NodeDecorator.DEPLOYMENT_CONTEXT_KEY, {})

    def set_cloud_node_ip(self, ip):
        self.__set(NodeDecorator.CLOUD_NODE_IP_KEY, ip)

    def get_cloud_node_ip(self):
        return self.__get(NodeDecorator.CLOUD_NODE_IP_KEY)

    def set_cloud_node_ssh_url(self, url):
        self.__set(NodeDecorator.CLOUD_NODE_SSH_URL_KEY, url)

    def get_cloud_node_ssh_url(self):
        return self.__get(NodeDecorator.CLOUD_NODE_SSH_URL_KEY)

    def set_cloud_node_ssh_password(self, password):
        self.__set(NodeDecorator.CLOUD_NODE_SSH_PASSWORD_KEY, password)

    def get_cloud_node_ssh_password(self):
        return self.__get(NodeDecorator.CLOUD_NODE_SSH_PASSWORD_KEY)

    def set_cloud_node_ssh_keypair_name(self, password):
        self.__set(NodeDecorator.CLOUD_NODE_SSH_KEYPAIR_NAME_KEY, password)

    def get_cloud_node_ssh_keypair_name(self):
        return self.__get(NodeDecorator.CLOUD_NODE_SSH_KEYPAIR_NAME_KEY)

    def set_cloud_node_ports_mapping(self, ip):
        self.__set(NodeDecorator.CLOUD_NODE_PORTS_MAPPING_KEY, ip)

    def get_cloud_node_ports_mapping(self):
        return self.__get(NodeDecorator.CLOUD_NODE_PORTS_MAPPING_KEY)

redpajama_set_name: RedPajamaGithub


text:
#include <znc/Modules.h>
#include <znc/znc.h>
#include <znc/User.h>

class CNotifyConnectMod : public CModule {
public:
	MODCONSTRUCTOR(CNotifyConnectMod) {}

	void OnClientLogin() override {
		SendAdmins(GetUser()->GetUserName() + " attached (from " + GetClient()->GetRemoteIP() + ")");
	}

	void OnClientDisconnect() override {
		SendAdmins(GetUser()->GetUserName() + " detached (from " + GetClient()->GetRemoteIP() + ")");
	}

private:
	void SendAdmins(const CString &msg) {
		CZNC::Get().Broadcast(msg, true, nullptr, GetClient());
	}
};

template<> void TModInfo<CNotifyConnectMod>(CModInfo& Info) {
	Info.SetWikiPage("notify_connect");
}

GLOBALMODULEDEFS(CNotifyConnectMod, "Notifies all admin users when a client connects or disconnects.")


text:
import React, { Component } from 'react';

export default class CEHFunctions extends Component{
    static CheckNumeric(val){
        if((val||val===0) && !isNaN(val) && isFinite(val))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

}


text:
package com.sopra.bbl.msa.dashboard;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.stream.EnableTurbineStream;

/**
 * Classe démarrant l'application de gestion des circuits Hystrix
 *
 * @author jntakpe
 */
@EnableTurbineStream
@SpringBootApplication
@EnableHystrixDashboard
public class DashboardApplication {

    public static void main(String[] args) {
        SpringApplication.run(DashboardApplication.class, args);
    }
}


text:
<?php
return [
		'KAZ-Canvas' => 'KAZ-Canvas',
		'Selecione um modelo para iniciar!' => 'Choose a model to start!',
		'Canvas de Modelo de Negocios' => 'Business Model Canvas',
		'Lean Model Canvas' => 'Lean Model Canvas',
		'Lingua' => 'Language',
		'Portugues' => 'Portuguese',
		'Ingles' => 'English',
		'Espanhol' => 'Spanish',
		'Equipe KZ-Canvas.' => 'KAZ-Canvas team.',
		// email projeto compartilhado
		'KZ-Canvas - um projeto foi compartilhado com voce' => 'KAZ-Canvas - a project has been shared with you',
		'O projeto {nomeProjetoCanvas} foi compartilhado com voce.' => 'The project {nomeProjetoCanvas} has been shared with you.',
		'Acesse {url} para visualizar o projeto compartilhado.' => 'Click {url} to visualize the shared project.',
		'AQUI' => 'HERE',
		'Utilize os seguintes dados para logar no sistema' => 'Login with the following credentials',
		'Usuario' => 'User',
		'Senha' => 'Password',
		'Sua senha' => 'Your password',
		// email para recuperar senha
		'KZ-Canvas - recuperar senha' => 'KAZ-Canvas - forgot password',
		'Uma solicitacao de troca de senha foi efetuada para o usuario' => 'A password recovery request has been done by the user',
		'Acesse {url} para definir uma nova senha.' => 'Click {url} to define a new password.',
		'Caso voce nao tenha solicitado a troca, pedimos que desconsidere esta mensagem.' =>
					'If you have not requested the password recovery, please disregard this message.',
		// bem vindo
		'KZ-Canvas - bem vindo' => 'KAZ-Canvas - welcome',
		'Seja bem vindo ao KZ-Canvas!' => 'Welcome to KAZ-Canvas!',
		'A partir de agora voce tera acesso a uma poderosa ferramenta de criacao de modelos canvas.' =>
				'From now you will have access to a powerful model canvas creation tool.',
		'Acesse {url} para comecar a criar seus modelos canvas.' => 'Click {url} to start creating your models canvas.',
];


text:
package example.nosql;

import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.ibm.twa.applab.client.WorkloadService;
import com.ibm.twa.applab.client.helpers.Step;
import com.ibm.twa.applab.client.helpers.TriggerFactory;
import com.ibm.twa.applab.client.helpers.WAProcess;
import com.ibm.twa.applab.client.helpers.steps.RestfulStep;
import com.ibm.tws.simpleui.bus.Task;
import com.ibm.tws.simpleui.bus.TaskLibrary;
import com.ibm.tws.simpleui.bus.Trigger;

public class WorkloadSchedulerClient {
	private static final String WORKLOAD_SCHEDULER = "WorkloadScheduler";
	private static final String AGENT_SUFFIX = "_CLOUD";

	// Once connected and authenticated correctly, this boolean is true
	private boolean connected = false;
	// Hold the instance of the WorkloadService
	private WorkloadService ws;

	private String cloudAgentName = "_CLOUD";

	//Enable debug mode if needed
	private boolean debugMode = false;

	// Default empty constructor.
	public WorkloadSchedulerClient(){};

	/**
	 *  Connects and authenticates to the server, exploring the content of
	 *  VCAP_SERVICES content.
	 *
	 *  @param o: Output Stream to write useful info
	 */
	public void connect() {
		 String vcapJSONString = System.getenv("VCAP_SERVICES");

    	if (vcapJSONString != null) {
    		// parse the VCAP JSON structure
    		JsonObject obj =  new JsonParser().parse(vcapJSONString).getAsJsonObject();
        	System.out.println("Looking for Workload Automation Service...");
    		Entry<String, JsonElement> wsEntry = null;
    		Set<Entry<String, JsonElement>> entries = obj.entrySet();
    		// Look for the VCAP key that holds the Workload Scheduler service information
    		for (Entry<String, JsonElement> eachEntry : entries) {
    			if (eachEntry.getKey().startsWith(WORKLOAD_SCHEDULER)) {
    				wsEntry = eachEntry;
    				break;
    			}
    		}

			if (wsEntry == null) {
				System.out.println("Could not connect: Workload Scheduler service information not found in VCAP_SERVICES!");
				throw new RuntimeException("Could not find " + WORKLOAD_SCHEDULER + " key in VCAP_SERVICES env variable");
			}

			JsonObject twaService = wsEntry.getValue().getAsJsonArray().get(0).getAsJsonObject();
			JsonObject credentials = twaService.get("credentials").getAsJsonObject();

			System.out.println("Starting Workload Automation connection..");
			String url = credentials.get("url").getAsString();
			int index = url.indexOf("tenantId=") + 9;
			String prefix = url.substring(index, index + 2);
			System.out.println("prefix=" + prefix);
			cloudAgentName = prefix + AGENT_SUFFIX;
			try {
//				WorkloadService.disableCertificateValidation();
				ws = new WorkloadService(url);
				ws.setDebugMode(debugMode);
			} catch (Exception e) {
				System.out.println("Could not connect to the service: " + e.getClass().getName() + " " + e.getMessage());
				return;
			}
			connected = true;
			System.out.println("Connection obtained.");
    	}
		else {
			throw new RuntimeException("VCAP_SERVICES not found");
		}

	}

	public synchronized Task setupProcess(String libName, String processName, String processDescription, String callbackURL) throws Exception {
		if (!connected) connect();

		Task process = null;

		// check if process exists
		List<Task> processes = ws.getTasks(ws.getDefaultLibrary());
		for (Task p : processes) {
			if (p.getName().equalsIgnoreCase(processName)) {
				process = p;
			}
		}

		// If not found, create the process
		if (process==null) {
			System.out.println("Creating Workload Scheduler Process...");
			// Use default xx_CLOUD agent to run the step
			String agentName = cloudAgentName;

			// Crate a new Process
			WAProcess p = new WAProcess(processName, processDescription); // Process name and description

			// Create a REST Step
//			RESTAction action = new RESTAction(callbackURL,"application/json","application/json",RestfulStep.POST_METHOD,null);
//			RESTAuthenticationData auth = RESTAuthenticationData.fromUserPwd("userName", "password");
//			RESTInput input = RESTInput.fromText("Your text body");
//			Step s1 = new RestfulStep(agentName, action, auth, input);

			Step s1 = new RestfulStep(agentName, callbackURL, "*/*", "text/plain", RestfulStep.GET_METHOD);
			p.addStep(s1);

			// Define trigger to run it every day at 10
			Trigger trigger = TriggerFactory.everyDayAt(10, 0);

			p.addTrigger(trigger);

			// Finally create and enable the process
		    process = ws.createAndEnableTask(p);
		}

		System.out.println("Workload Scheduler Process id: "+process.getId());
		return process;
	}

}


text:
package api

import (
	"crypto/ecdsa"
	"crypto/rand"
	"crypto/x509"
	"encoding/asn1"
	"errors"
	"time"

	"github.com/fabric_sdk_golang/db"
	"github.com/fabric_sdk_golang/utils"
	"golang.org/x/net/context"

	pb "github.com/fabric_sdk_golang/ca/protos"
	"github.com/fabric_sdk_golang/core/crypto/primitives"
	"github.com/fabric_sdk_golang/core/crypto/primitives/ecies"
	"github.com/golang/protobuf/proto"
	google_protobuf "github.com/golang/protobuf/ptypes/timestamp"
	"google.golang.org/grpc"
)

var (
	// ECertSubjectRole is the ASN1 object identifier of the subject's role.
	ECertSubjectRole = asn1.ObjectIdentifier{2, 1, 3, 4, 5, 6, 7}
)

///获取ECAA客户端
func (mbsrvc *memberImpl) getECAAClient() (*grpc.ClientConn, pb.ECAAClient, error) {

	conn, err := getClientConn()
	if err != nil {
		logger.Errorf("Failed getting client connection: [%s]", err)
		return nil, nil, err
	}

	client := pb.NewECAAClient(conn)

	logger.Debug("Getting ECAA client...done")

	return conn, client, nil
}

///获取ECA客户端
func (mbsrvc *memberImpl) getECAClient() (*grpc.ClientConn, pb.ECAPClient, error) {

	conn, err := getClientConn()
	if err != nil {
		logger.Errorf("Failed getting client connection: [%s]", err)
		return nil, nil, err
	}

	client := pb.NewECAPClient(conn)

	logger.Debug("Getting ECA client...done")

	return conn, client, nil
}

//helper function for multiple tests
func (mbsrvc *memberImpl) Enroll(user *User) (interface{}, []byte, []byte, error) {
	conn, ecap, err := mbsrvc.getECAClient()
	if err != nil {
		logger.Error(err)
		return nil, nil, nil, err
	}
	defer conn.Close()
	logger.Debugf("连接正常")
	// Phase 1 of the protocol: Generate crypto material

	signPriv, err := primitives.NewECDSAKey()
	user.EnrollPrivKey = signPriv
	if err != nil {
		return nil, nil, nil, err
	}
	signPub, err := x509.MarshalPKIXPublicKey(&signPriv.PublicKey)
	if err != nil {
		return nil, nil, nil, err
	}

	encPriv, err := primitives.NewECDSAKey()
	if err != nil {
		return nil, nil, nil, err
	}
	encPub, err := x509.MarshalPKIXPublicKey(&encPriv.PublicKey)
	if err != nil {
		return nil, nil, nil, err
	}
	logger.Debug("x509.MarshalPKIXPublicKey(&encPriv.PublicKey)")
	req := &pb.ECertCreateReq{
		Ts:   &google_protobuf.Timestamp{Seconds: time.Now().Unix(), Nanos: 0},
		Id:   &pb.Identity{Id: user.EnrollID},
		Tok:  &pb.Token{Tok: user.EnrollPwd},
		Sign: &pb.PublicKey{Type: pb.CryptoType_ECDSA, Key: signPub},
		Enc:  &pb.PublicKey{Type: pb.CryptoType_ECDSA, Key: encPub},
		Sig:  nil}
	logger.Debug("resp, err := ecap.CreateCertificatePair(context.Background(), req) start")
	resp, err := ecap.CreateCertificatePair(context.Background(), req)
	logger.Debug("resp, err := ecap.CreateCertificatePair(context.Background(), req)")
	if err != nil {
		return nil, nil, nil, err
	}

	//Phase 2 of the protocol
	spi := ecies.NewSPI()
	eciesKey, err := spi.NewPrivateKey(nil, encPriv)
	if err != nil {
		return nil, nil, nil, err
	}

	ecies, err := spi.NewAsymmetricCipherFromPublicKey(eciesKey)
	if err != nil {
		return nil, nil, nil, err
	}

	out, err := ecies.Process(resp.Tok.Tok)
	if err != nil {
		return nil, nil, nil, err
	}

	req.Tok.Tok = out
	req.Sig = nil

	hash := primitives.NewHash()
	raw, _ := proto.Marshal(req)
	hash.Write(raw)

	r, s, err := ecdsa.Sign(rand.Reader, signPriv, hash.Sum(nil))
	if err != nil {
		return nil, nil, nil, err
	}
	R, _ := r.MarshalText()
	S, _ := s.MarshalText()
	req.Sig = &pb.Signature{Type: pb.CryptoType_ECDSA, R: R, S: S}

	resp, err = ecap.CreateCertificatePair(context.Background(), req)
	if err != nil {
		return nil, nil, nil, err
	}

	// Verify we got valid crypto material back
	x509SignCert, err := primitives.DERToX509Certificate(resp.Certs.Sign)
	if err != nil {
		return nil, nil, nil, err
	}

	_, err = primitives.GetCriticalExtension(x509SignCert, ECertSubjectRole)
	if err != nil {
		return nil, nil, nil, err
	}

	x509EncCert, err := primitives.DERToX509Certificate(resp.Certs.Enc)
	if err != nil {
		return nil, nil, nil, err
	}

	_, err = primitives.GetCriticalExtension(x509EncCert, ECertSubjectRole)
	if err != nil {
		return nil, nil, nil, err
	}

	sqlex := &db.SqlDB{}
	if sqlex == nil {
		logger.Error("Null pointer deference")
		return nil, nil, nil, errors.New("Null pointer deference")
	}

	priv, err := utils.PrivToString(signPriv)
	if err != nil {
		logger.Error(err)
		return nil, nil, nil, err
	}

	strPkChain := string(resp.Pkchain)
	var userInfoTemp db.UsersInfo
	userInfoTemp.UserId = user.EnrollID
	userInfoTemp.Token = string(user.EnrollPwd)
	userInfoTemp.Priv = priv
	userInfoTemp.PkChain = strPkChain
	err = sqlex.ADDUser(&userInfoTemp)
	if err != nil {
		logger.Error(err)
		return nil, nil, nil, err
	}
	return signPriv, resp.Certs.Sign, resp.Pkchain, nil
}

func (mbsrvc *memberImpl) Registrar(registrar User, user *User) error {
	conn, ecaa, err := mbsrvc.getECAAClient()
	if err != nil {
		return err
	}
	defer conn.Close()
	//create req
	req := &pb.RegisterUserReq{
		Id:   &pb.Identity{Id: user.EnrollID},
		Role: pb.Role(user.Role),
		//Account:     user.Affiliation,
		Affiliation: user.Affiliation,
		Registrar: &pb.Registrar{
			Id:            &pb.Identity{Id: registrar.EnrollID},
			Roles:         user.RegistrarRoles,
			DelegateRoles: user.RegistrarDelegateRoles,
		},
		Sig: nil}

	//sign the req
	hash := primitives.NewHash()
	raw, _ := proto.Marshal(req)
	hash.Write(raw)

	r, s, err := ecdsa.Sign(rand.Reader, registrar.EnrollPrivKey, hash.Sum(nil))
	if err != nil {
		msg := "Failed to register user. Error (ECDSA) signing request: " + err.Error()
		return errors.New(msg)
	}
	R, _ := r.MarshalText()
	S, _ := s.MarshalText()
	req.Sig = &pb.Signature{Type: pb.CryptoType_ECDSA, R: R, S: S}

	token, err := ecaa.RegisterUser(context.Background(), req)
	if err != nil {
		return err
	}

	if token == nil {
		return errors.New("Failed to obtain token")
	}

	//need the token for later tests
	user.EnrollPwd = token.Tok

	return nil
}


text:
from __future__ import unicode_literals

import datetime
from django.db import migrations, models
from django.utils.timezone import utc

class Migration(migrations.Migration):

    dependencies = [
        ('frbb', '0007_userprofile_withdrawn'),
    ]

    operations = [
        migrations.AddField(
            model_name='poem',
            name='created',
            field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 5, 24, 3, 41, 34, 773855, tzinfo=utc)),
            preserve_default=False,
        ),
        migrations.AddField(
            model_name='userprofile',
            name='created',
            field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 5, 24, 3, 41, 41, 245833, tzinfo=utc)),
            preserve_default=False,
        ),
        migrations.AlterField(
            model_name='userprofile',
            name='balance',
            field=models.IntegerField(default=5),
        ),
    ]


text:
module Mindset
    class MockDevice
        # packet_size_bytes sets how much of the content is returned on each call to
        # read, this is a maximum, if the stream contains less than this amount then
        # only the stream length bytes are returned.
        #
        # If repeat_stream is true then the device will repeat sending its contents
        # via read
        def initialize(packet_size_bytes = 1024, repeat_stream = false)
            @packet_size_bytes = packet_size_bytes
            @repeat_stream = repeat_stream
            @stream = []
            @stream_index = 0
        end

        # Act like the real device, so code can be kept similar
        def listen(address, channel)
            yield self
        end

        # Returns a "stream" of bytes, this is chunked by up to @packet_size_bytes
        def read
            # Try to fetch @packet_size_bytes from @stream at the current stream index
            send_bytes = @stream[@stream_index, @packet_size_bytes]

            # If we fail to get @packet_size_bytes then try to fetch the remaining from the head of the stream
            if @repeat_stream and (send_bytes.length < @packet_size_bytes)
                # We can only fetch up to the current stream pointer i.e. the current stream content
                # may not be enough to satisfy the full packet size
                bytes_before = @stream[0, [@stream_index, @packet_size_bytes - send_bytes.length].min]
                send_bytes.concat(bytes_before)
            end
            @stream_index += send_bytes.length
            # Only wrap the index if we are repeating
            @stream_index = (@stream_index % @stream.length) if @repeat_stream
            send_bytes
        end

        def queue_event_battery(value)
            assert_8_bit(value)
            add_packet(Parser_code_battery, [value])
            value
        end

        def queue_event_poor_quality(value)
            assert_8_bit(value)
            add_packet(Parser_code_poor_quality, [value])
            value
        end

        def queue_event_attention(value)
            assert_8_bit(value)
            add_packet(Parser_code_attention, [value])
            value
        end

        def queue_event_meditation(value)
            assert_8_bit(value)
            add_packet(Parser_code_meditation, [value])
            value
        end

        def queue_event_raw_marker(value)
            assert_8_bit(value)
            add_packet(Parser_code_raw_marker, [value])
            value
        end

        def queue_event_raw_8_bit_signal(value)
            assert_8_bit(value)
            add_packet(Parser_code_8bitraw_signal, [value])
            value
        end

        def queue_event_raw_16_bit_signal(value)
            assert_16_bit(value)
            add_packet(Parser_code_raw_signal, [(value & 0xFF00) >> 8, value & 0xFF])
            value
        end

        # values is a hash with the following expected key => int 24 values
        # :delta, :theta, :low_alpha, :high_alpha, :low_beta, :high_beta, :low_gamma, :mid_gamma
        def queue_event_asic_eeg_power(powers)
            keys = [:delta, :theta, :low_alpha, :high_alpha, :low_beta, :high_beta, :low_gamma, :mid_gamma]
            payload = []
            keys.each do |key|
                power_value = powers[key]
                assert_24_bit(power_value)
                payload << ((power_value & 0xFF0000) >> 16)
                payload << ((power_value & 0x00FF00) >> 8)
                payload <<  (power_value & 0x0000FF)
            end
            add_packet(Parser_code_asic_eeg_power_int, payload)
            powers
        end

        def add_packet(code, payload)
            # No ext codes for now
            payload_length_with_code = payload.length + 1
            raise("payload too long") if payload_length_with_code >= Parser_sync_byte
            packet = [Parser_sync_byte, Parser_sync_byte, payload_length_with_code]
            packet.concat(make_payload(code, payload))
            packet << Mindset.compute_required_checksum([code].concat(payload))
            @stream.concat(packet)
        end

        # Not using extended codes
        def make_payload(code, payload)
            [code].concat(payload)
        end

        def assert_8_bit(value)
            raise("Not a byte #{value}") if value > 0xFF
        end

        def assert_16_bit(value)
            raise("Not a word #{value}") if value > 0xFFFF
        end

        def assert_24_bit(value)
            raise("Not an int value #{value}") if value > 0xFFFFFF
        end
    end
end