1 /* Cycript - Optimizing JavaScript Compiler/Runtime
 
   2  * Copyright (C) 2009-2015  Jay Freeman (saurik)
 
   5 /* GNU Affero General Public License, Version 3 {{{ */
 
   7  * This program is free software: you can redistribute it and/or modify
 
   8  * it under the terms of the GNU Affero General Public License as published by
 
   9  * the Free Software Foundation, either version 3 of the License, or
 
  10  * (at your option) any later version.
 
  12  * This program is distributed in the hope that it will be useful,
 
  13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  15  * GNU Affero General Public License for more details.
 
  17  * You should have received a copy of the GNU Affero General Public License
 
  18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
  28 let $cy_set = function(object, properties) {
 
  29     for (const name in properties)
 
  30         Object.defineProperty(object, name, {
 
  34             value: properties[name],
 
  45 extern "C" int access(const char *path, int amode);
 
  46 extern "C" char *getcwd(char *buf, size_t size);
 
  47 extern "C" int getpid();
 
  49 $cy_set(Date.prototype, {
 
  51         return `new ${this.constructor.name}(${this.toUTCString().toCYON()})`;
 
  55 $cy_set(Error.prototype, {
 
  57         let stack = this.stack.split('\n');
 
  58         if (stack.slice(-1)[0] == "global code")
 
  59             stack = stack.slice(0, -1);
 
  60         for (let i = 0; i != stack.length; ++i)
 
  61             stack[i] = '\n    ' + stack[i];
 
  62         return `new ${this.constructor.name}(${this.message.toCYON()}) /*${stack.join('')} */`;
 
  66 let IsFile = function(path) {
 
  67     // XXX: this doesn't work on symlinks, but I don't want to fix stat :/
 
  68     return access(path, F_OK) == 0 && access(path + '/', F_OK) == -1;
 
  71 let StartsWith = function(lhs, rhs) {
 
  72     return lhs.substring(0, rhs.length) == rhs;
 
  75 let ResolveFile = function(exact, name) {
 
  76     if (exact && IsFile(name))
 
  78     for (let suffix of ['.js', '.json'])
 
  79         if (IsFile(name + suffix))
 
  85 let GetLibraryPath = function() {
 
  86     let handle = dlopen("/usr/lib/libcycript.dylib", RTLD_NOLOAD);
 
  91         let CYHandleServer = dlsym(handle, "CYHandleServer");
 
  92         if (CYHandleServer == null)
 
  95         let info = new Dl_info;
 
  96         if (dladdr(CYHandleServer, info) == 0)
 
  99         let path = info->dli_fname;
 
 100         let slash = path.lastIndexOf('/');
 
 104         return path.substr(0, slash);
 
 110 let ResolveFolder = function(name) {
 
 111     if (access(name + '/', F_OK) == -1)
 
 114     if (IsFile(name + "/package.json")) {
 
 115         let package = require(name + "/package.json");
 
 116         let path = ResolveFile(true, name + "/" + package.main);
 
 121     return ResolveFile(false, name + "/index");
 
 124 let ResolveEither = function(name) {
 
 127         path = ResolveFile(true, name);
 
 129         path = ResolveFolder(name);
 
 133 require.resolve = function(name) {
 
 134     if (StartsWith(name, '/')) {
 
 135         let path = ResolveEither(name);
 
 139         let cwd = new (typedef char[1024]);
 
 140         cwd = getcwd(cwd, cwd.length).toString();
 
 141         cwd = cwd.split('/');
 
 143         if (StartsWith(name, './') || StartsWith(name, '../')) {
 
 144             let path = ResolveEither(cwd + '/' + name);
 
 148             for (let i = cwd.length; i != 0; --i) {
 
 149                 let modules = cwd.slice(0, i).concat("node_modules").join('/');
 
 150                 let path = ResolveEither(modules + "/" + name);
 
 155             let library = GetLibraryPath();
 
 156             let path = ResolveFile(true, library + "/cycript0.9/" + name + ".cy");
 
 162     throw new Error("Cannot find module '" + name + "'");
 
 167 process.binding = function(name) {
 
 168     let binding = bindings[name];
 
 169     if (typeof binding != 'undefined')
 
 173         case 'buffer': binding = {
 
 178         case 'cares_wrap': binding = {
 
 181         case 'constants': binding = {
 
 184         case 'fs': binding = {
 
 189                 throw new Error("stat(" + arguments[0] + ")");
 
 193         case 'pipe_wrap': binding = {
 
 196         case 'smalloc': binding = {
 
 201         case 'stream_wrap': binding = {
 
 204         case 'tcp_wrap': binding = {
 
 207         case 'timer_wrap': binding = {
 
 213         case 'tty_wrap': binding = {
 
 216         case 'uv': binding = {
 
 220             throw new Error('No such module: ' + name);
 
 223     bindings[name] = binding;
 
 227 let environ = *(typedef char ***)(dlsym(RTLD_DEFAULT, "environ"));
 
 228 for (let i = 0; environ[i] != null; ++i) {
 
 229     let assign = environ[i];
 
 230     let equal = assign.indexOf('=');
 
 231     let name = assign.substr(0, equal);
 
 232     let value = assign.substr(equal + 1);
 
 233     process.env[name.toString()] = value;
 
 236 process.pid = getpid();