19258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org// Copyright 2006-2008 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org"use strict";
6a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org
743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This file contains infrastructure used by the API.  See
843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// v8natives.js for an explanation of these files are processed and
943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// loaded.
1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction CreateDate(time) {
135d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org  var date = new $Date();
1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  date.setTime(time);
1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return date;
1641044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1910480471c0db59c51c15e57d2a3489551d61b273jkummerow@chromium.orgvar kApiFunctionCache = new InternalArray();
20f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgvar functionCache = kApiFunctionCache;
2143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2341044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.orgfunction Instantiate(data, name) {
2443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (!%IsTemplate(data)) return data;
2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var tag = %GetTemplateField(data, kApiTagOffset);
2643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  switch (tag) {
2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case kFunctionTag:
2841044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org      return InstantiateFunction(data, name);
2943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case kNewObjectTag:
3043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      var Constructor = %GetTemplateField(data, kApiConstructorOffset);
314acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      // Note: Do not directly use a function template as a condition, our
324acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      // internal ToBoolean doesn't handle that!
33248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      var result;
34248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      if (typeof Constructor === 'undefined') {
35248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org        result = {};
36248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org        ConfigureTemplateInstance(result, data);
37248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      } else {
38248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org        // ConfigureTemplateInstance is implicitly called before calling the API
39248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org        // constructor in HandleApiCall.
40248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org        result = new (Instantiate(Constructor))();
41248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org        result = %ToFastProperties(result);
42248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      }
4343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return result;
4443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    default:
4543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      throw 'Unknown API tag <' + tag + '>';
4643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
4741044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
4843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5041044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.orgfunction InstantiateFunction(data, name) {
513291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // We need a reference to kApiFunctionCache in the stack frame
523291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // if we need to bail out from a stack overflow.
533291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  var cache = kApiFunctionCache;
5443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var serialNumber = %GetTemplateField(data, kApiSerialNumberOffset);
553291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  var isFunctionCached =
563291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org   (serialNumber in cache) && (cache[serialNumber] != kUninitialized);
573291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  if (!isFunctionCached) {
583291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    try {
592c99e28a7b1fcb3767dc7c0088514fe53be784c5ricow@chromium.org      var flags = %GetTemplateField(data, kApiFlagOffset);
60a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org      var prototype;
613c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org      if (!(flags & (1 << kRemovePrototypeBit))) {
62a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org        var template = %GetTemplateField(data, kApiPrototypeTemplateOffset);
63a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org        prototype = typeof template === 'undefined'
64a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org            ?  {} : Instantiate(template);
65a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org
66662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org        var parent = %GetTemplateField(data, kApiParentTemplateOffset);
67662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org        // Note: Do not directly use a function template as a condition, our
68662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org        // internal ToBoolean doesn't handle that!
69a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org        if (typeof parent !== 'undefined') {
70662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org          var parent_fun = Instantiate(parent);
7131c0e32e19ad3df48525fa9e7b2d1c0c07496d00machenbach@chromium.org          %InternalSetPrototype(prototype, parent_fun.prototype);
72662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org        }
733291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org      }
74a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org      var fun = %CreateApiFunction(data, prototype);
75a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      if (IS_STRING(name)) %FunctionSetName(fun, name);
76a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org      var doNotCache = flags & (1 << kDoNotCacheBit);
77a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org      if (!doNotCache) cache[serialNumber] = fun;
783291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org      ConfigureTemplateInstance(fun, data);
79639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org      if (doNotCache) return fun;
803291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    } catch (e) {
813291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org      cache[serialNumber] = kUninitialized;
823291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org      throw e;
8343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
8443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
853291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  return cache[serialNumber];
8641044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
8743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
8843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
8943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenfunction ConfigureTemplateInstance(obj, data) {
9043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  var properties = %GetTemplateField(data, kApiPropertyListOffset);
911e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  if (!properties) return;
921e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Disable access checks while instantiating the object.
931e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  var requires_access_checks = %DisableAccessChecks(obj);
941e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  try {
951e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    for (var i = 1; i < properties[0];) {
961e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      var length = properties[i];
971e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      if (length == 3) {
98870a0b67c822d289024711912e2512af01b66c3bager@chromium.org        var name = properties[i + 1];
99870a0b67c822d289024711912e2512af01b66c3bager@chromium.org        var prop_data = properties[i + 2];
100870a0b67c822d289024711912e2512af01b66c3bager@chromium.org        var attributes = properties[i + 3];
101870a0b67c822d289024711912e2512af01b66c3bager@chromium.org        var value = Instantiate(prop_data, name);
1025de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org        %AddPropertyForTemplate(obj, name, value, attributes);
103975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org      } else if (length == 4 || length == 5) {
104975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org        // TODO(verwaest): The 5th value used to be access_control. Remove once
105975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org        // the bindings are updated.
1061e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org        var name = properties[i + 1];
107dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org        var getter = properties[i + 2];
108dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org        var setter = properties[i + 3];
1091e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org        var attribute = properties[i + 4];
110dc207d99f9dbff76065405b65f3d88e1fb49fc1cmachenbach@chromium.org        %DefineApiAccessorProperty(obj, name, getter, setter, attribute);
1111e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      } else {
1121e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org        throw "Bad properties array";
113870a0b67c822d289024711912e2512af01b66c3bager@chromium.org      }
1141e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      i += length + 1;
11543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
1161e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  } finally {
1171e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    if (requires_access_checks) %EnableAccessChecks(obj);
11843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
11941044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org}
120