Distinguish between dedicated versus stem cell runtimes (#237)

diff --git a/knative-build/runtimes/javascript/platform/knative.js b/knative-build/runtimes/javascript/platform/knative.js
index cf08873..f1a69db 100644
--- a/knative-build/runtimes/javascript/platform/knative.js
+++ b/knative-build/runtimes/javascript/platform/knative.js
@@ -22,6 +22,86 @@
 const CONTENT_TYPE = "Content-Type";
 
 /**
+ * Determine if runtime is a "stem" cell, i.e., can be initialized with request init. data
+ * @param env
+ * @returns {boolean}
+ */
+function isStemCell(env) {
+    let actionCode = env.__OW_ACTION_CODE;
+    // It is a stem cell if valid code is "built into" the runtime's process environment.
+    return (typeof actionCode === 'undefined' || actionCode.length === 0);
+}
+
+/**
+ * Determine if the request (body) contains valid activation data.
+ * @param req
+ * @returns {boolean}
+ */
+function hasActivationData(req) {
+    // it is a valid activation if the body contains an activation and value keys with data.
+    if (typeof req.body !== "undefined" &&
+        typeof req.body.activation !== "undefined" &&
+        typeof req.body.value !== "undefined") {
+        return true;
+    }
+    return false;
+}
+
+/**
+ * Determine if the request (body) contains valid init data.
+ * @param req
+ * @returns {boolean}
+ */
+function hasInitData(req) {
+    // it is a valid init. if the body contains an init key with data.
+    if (typeof req.body !== "undefined" &&
+        typeof req.body.init !== "undefined") {
+        return true;
+    }
+    return false;
+}
+
+/**
+ * Determine if runtime is a "stem" cell, i.e., can be initialized with request init. data
+ * @param env
+ * @returns {boolean}
+ */
+function isStemCell(env) {
+    let actionCode = env.__OW_ACTION_CODE;
+    // It is a stem cell if valid code is "built into" the runtime's process environment.
+    return (typeof actionCode === 'undefined' || actionCode.length === 0);
+}
+
+/**
+ * Determine if the request (body) contains valid activation data.
+ * @param req
+ * @returns {boolean}
+ */
+function hasActivationData(req) {
+    // it is a valid activation if the body contains an activation and value keys with data.
+    if (typeof req.body !== "undefined" &&
+        typeof req.body.activation !== "undefined" &&
+        typeof req.body.value !== "undefined") {
+        return true;
+    }
+    return false;
+}
+
+/**
+ * Determine if the request (body) contains valid init data.
+ * @param req
+ * @returns {boolean}
+ */
+function hasInitData(req) {
+    // it is a valid init. if the body contains an init key with data.
+    if (typeof req.body !== "undefined" &&
+        typeof req.body.init !== "undefined") {
+        return true;
+    }
+    return false;
+}
+
+/**
  * Pre-process the incoming
  */
 function preProcessInitData(env, initdata, valuedata, activationdata) {
@@ -54,13 +134,19 @@
             if (initdata.code && typeof initdata.code === 'string') {
                 code = initdata.code;
             }
-            if (initdata.binary && typeof initdata.binary === 'boolean') {
-                // TODO: Throw error if BINARY is not 'true' or 'false'
-                binary = initdata.binary;
+            if (initdata.binary) {
+                if (typeof initdata.binary === 'boolean') {
+                    binary = initdata.binary;
+                } else {
+                    throw ("Invalid Init. data; expected boolean for key 'binary'.");
+                }
             }
-            if (initdata.raw && typeof initdata.raw === 'boolean') {
-                // TODO: Throw error if RAW is not 'true' or 'false'
-                raw = initdata.raw;
+            if (initdata.raw ) {
+                if (typeof initdata.raw === 'boolean') {
+                    raw = initdata.raw;
+                } else {
+                    throw ("Invalid Init. data; expected boolean for key 'raw'.");
+                }
             }
         }
 
@@ -81,7 +167,6 @@
                 activationdata.action_name = actionName;
             }
         }
-
         DEBUG.dumpObject(valuedata.main, "valuedata.main");
         DEBUG.dumpObject(valuedata.code , "valuedata.code");
         DEBUG.dumpObject(valuedata.binary, "valuedata.binary");
@@ -167,7 +252,7 @@
  */
 function preProcessRequest(req){
     DEBUG.functionStart();
-    try{
+    try {
         // Get or create valid references to the various data we might encounter
         // in a request such as Init., Activation and function parameter data.
         let body = req.body || {};
@@ -296,7 +381,6 @@
     DEBUG.functionEnd();
 }
 
-
 function PlatformKnativeImpl(platformFactory) {
     DEBUG.functionStart();
     DEBUG.dumpObject(platformFactory, "platformFactory" );
@@ -318,13 +402,16 @@
     this.run = function(req, res) {
 
         try {
-
             DEBUG.dumpObject(service.initialized(),"service.initialized()");
 
             // Process request and process env. variables to provide them in the manner
             // an OpenWhisk Action expects them, as well as enable additional Http features.
             preProcessRequest(req);
 
+            // Do not process requests with init. data if this is not a "stem" cell
+            if (hasInitData(req) && !isStemCell(process.env))
+                throw ("Cannot initialize a runtime with a dedicated function.");
+
             service.initCode(req).then(function () {
                 service.runCode(req).then(function (result) {
                     postProcessResponse(req, result, res)
diff --git a/knative-build/runtimes/javascript/platform/platform.js b/knative-build/runtimes/javascript/platform/platform.js
index 2af5874..8e792a0 100644
--- a/knative-build/runtimes/javascript/platform/platform.js
+++ b/knative-build/runtimes/javascript/platform/platform.js
@@ -84,7 +84,7 @@
      * validate if a platform ID is a known, supported value
      * @param id Platform Id
      */
-    static isSupportedPlatform(id){
+    static isSupportedPlatform(id) {
         if (SUPPORTED_PLATFORMS.indexOf(id) > -1) {
             return true;
         }
@@ -96,8 +96,7 @@
      * @param id Platform ID
      * @returns {PlatformImpl} Platform instance (interface), as best can be done with NodeJS
      */
-    // TODO remove "app" parameter once we have a valid openwhisk platformImpl.
-    createPlatformImpl(id){
+    createPlatformImpl(id) {
         DEBUG.functionStart();
         DEBUG.dumpObject(id,"id");
         // Load the appropriate implementation module and return reference to it
diff --git a/knative-build/runtimes/javascript/src/service.js b/knative-build/runtimes/javascript/src/service.js
index b0d335e..726e167 100644
--- a/knative-build/runtimes/javascript/src/service.js
+++ b/knative-build/runtimes/javascript/src/service.js
@@ -68,11 +68,8 @@
      * created a NodeActionRunner.
      * @returns {boolean}
      */
-    this.initialized = function isIntialized(){
-        if( userCodeRunner === undefined ){
-            return false;
-        }
-        return true;
+    this.initialized = function isInitialized(){
+        return (typeof userCodeRunner !== "undefined");
     };
 
     /**