Skip to content

Commit

Permalink
Math.LOG2E precision issue + new demos [ci skip]
Browse files Browse the repository at this point in the history
- swift + jsc
- java + rhino
- XMLHttpRequest and friends
  • Loading branch information
SheetJSDev committed Sep 5, 2017
1 parent e34b6e7 commit ad47cb4
Show file tree
Hide file tree
Showing 47 changed files with 822 additions and 26 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This log is intended to keep track of backwards-incompatible changes, including
but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code.

## Unreleased (2017-08-??)
## 0.11.3 (2017-08-19)

* XLS cell ixfe/XF removed

Expand Down
32 changes: 28 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,24 +167,25 @@ CDNjs automatically pulls the latest version and makes all versions available at

The `demos` directory includes sample projects for:

**Frameworks**
**JS Frameworks and APIs**
- [`angular 1.x`](demos/angular/)
- [`angular 2.x / 4.x`](demos/angular2/)
- [`meteor`](demos/meteor/)
- [`vue 2`](demos/vue/)
- [`vue 2.x`](demos/vue/)
- [`XMLHttpRequest and fetch`](demos/xhr/)

**JS Bundlers and Tooling**
- [`browserify`](demos/browserify/)
- [`requirejs`](demos/requirejs/)
- [`rollup`](demos/rollup/)
- [`systemjs`](demos/systemjs/)
- [`webpack`](demos/webpack/)
- [`webpack 2.x`](demos/webpack/)

**JS Platforms and Integrations**
- [`Adobe ExtendScript`](demos/extendscript/)
- [`Headless Browsers`](demos/headless/)
- [`canvas-datagrid`](demos/datagrid/)
- [`Other JS engines`](demos/altjs/)
- [`Swift JSC and other engines`](demos/altjs/)

### Optional Modules

Expand Down Expand Up @@ -616,6 +617,29 @@ saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), "test.xlsx");
```
</details>

<details>
<summary><b>Browser upload to server</b> (click to show)</summary>

A complete example using XHR is [included in the xhr demo](demos/xhr/), along
with examples for fetch and wrapper libraries. This example assumes the server
can handle Base64-encoded files (see the demo for a basic nodejs server):

```js
/* in this example, send a base64 string to the server */
var wopts = { bookType:'xlsx', bookSST:false, type:'base64' };

var wbout = XLSX.write(workbook,wopts);

var oReq = new XMLHttpRequest();
oReq.open("POST", "/upload", true);
var formdata = new FormData();
formdata.append('file', 'test.xlsx'); // <-- server expects `file` to hold name
formdata.append('data', wbout); // <-- `data` holds the base64-encoded data
oReq.send(formdata);
```

</details>

### Writing Examples

- <http://sheetjs.com/demos/table.html> exporting an HTML table
Expand Down
4 changes: 2 additions & 2 deletions bits/23_binutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ function write_double_le(b, v/*:number*/, idx/*:number*/) {
var av = bs ? -v : v;
if(!isFinite(av)) { e = 0x7ff; m = isNaN(v) ? 0x6969 : 0; }
else {
e = Math.floor(Math.log(av) * Math.LOG2E);
m = v * Math.pow(2, 52 - e);
e = Math.floor(Math.log(av) / Math.LN2);
m = av * Math.pow(2, 52 - e);
if(e <= -1023 && (!isFinite(m) || m < Math.pow(2,52))) { e = -1022; }
else { m -= Math.pow(2,52); e+=1023; }
}
Expand Down
4 changes: 4 additions & 0 deletions demos/altjs/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
jvm-npm.js
sheetjs.*
*.class
*.jar
rhino
xlsx.swift.js
31 changes: 30 additions & 1 deletion demos/altjs/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.PHONY: all
all: duktape nashorn
all: duktape nashorn rhinojs swift

.PHONY: base
base:
Expand All @@ -13,3 +13,32 @@ duktape: base ## duktape / skookum demo
nashorn: base ## nashorn demo
if [ ! -e jvm-npm.js ]; then curl -O https://rawgit.com/nodyn/jvm-npm/master/src/main/javascript/jvm-npm.js; fi
jjs nashorn.js

.PHONY: swift
swift: base ## swift demo
if [ ! -e xlsx.swift.js ]; then cp ../../dist/xlsx.full.min.js xlsx.swift.js; fi
./SheetJSCore.swift

.PHONY: rhinojs ## rhino demo
rhinojs: base SheetJSRhino.class
java -cp .:SheetJS.jar:rhino.jar SheetJSRhino sheetjs.xlsx
java -cp .:SheetJS.jar:rhino.jar SheetJSRhino sheetjs.xlsb
java -cp .:SheetJS.jar:rhino.jar SheetJSRhino sheetjs.xls
java -cp .:SheetJS.jar:rhino.jar SheetJSRhino sheetjs.xml.xls

RHDEPS=$(filter-out SheetJSRhino.class,$(patsubst %.java,%.class,$(wildcard com/sheetjs/*.java)))
$(RHDEPS): %.class: %.java rhino.jar
javac -cp .:SheetJS.jar:rhino.jar $*.java

SheetJSRhino.class: $(RHDEPS)
jar -cf SheetJS.jar $^ ../../dist/xlsx.full.min.js
javac -cp .:SheetJS.jar:rhino.jar SheetJSRhino.java

rhino.jar:
if [ ! -e rhino ]; then git clone https://github.com/mozilla/rhino; fi
if [ ! -e rhino/build/rhino*/js.jar ]; then cd rhino; ant jar; fi
cp rhino/build/rhino*/js.jar rhino.jar

.PHONY: clean
clean:
rm SheetJS.jar *.class com/sheetjs/*.class
29 changes: 29 additions & 0 deletions demos/altjs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ optimize for low overhead and others optimize for ease of embedding within other
applications. Since it was designed for ES3 engines, the library can be used in
those settings! This demo tries to demonstrate a few alternative deployments.

Some engines provide no default global object. To create a global reference:

```js
var global = (function(){ return this; }).call(null);
```


## Swift + JavaScriptCore

iOS and OSX ship with the JavaScriptCore framework, enabling easy JS access from
Swift and Objective-C. Hybrid function invocation is tricky, but explicit data
passing is straightforward.

Binary strings can be passed back and forth using `String.Encoding.ascii`.


## Nashorn

Expand All @@ -21,6 +36,20 @@ a byte array. To use in `XLSX.read`, the demo copies the bytes into a plain JS
array and calls `XLSX.read` with type `"array"`.


## Rhino

[Rhino](http://www.mozilla.org/rhino) is an ES3+ engine written in Java. The
`SheetJSRhino` class and `com.sheetjs` package show a complete JAR deployment,
including the full XLSX source.

Due to code generation errors, optimization must be disabled:

```java
Context context = Context.enter();
context.setOptimizationLevel(-1);
```


## duktape and skookum

[Duktape](http://duktape.org/) is an embeddable JS engine written in C. The
Expand Down
62 changes: 62 additions & 0 deletions demos/altjs/SheetJSCore.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env xcrun swift

import JavaScriptCore;

class SheetJS {
var context: JSContext!;
var XLSX: JSValue!;

enum SJSError: Error {
case badJSContext;
};

func init_context() throws -> JSContext {
var context: JSContext!
do {
context = JSContext();
context.exceptionHandler = { ctx, X in if let e = X { print(e.toString()); }; }
var src = "var global = (function(){ return this; }).call(null);";
context.evaluateScript(src);
src = try String(contentsOfFile: "xlsx.swift.js");
context.evaluateScript(src);
if context != nil { return context!; }
} catch { print(error.localizedDescription); }
throw SheetJS.SJSError.badJSContext;
}

func version() throws -> String {
if let version = XLSX.objectForKeyedSubscript("version") { return version.toString(); }
throw SheetJS.SJSError.badJSContext;
}

func readFileToCSV(file: String) throws -> String {
let data:String! = try String(contentsOfFile: file, encoding:String.Encoding.ascii);
self.context.setObject(data, forKeyedSubscript:"payload" as (NSCopying & NSObjectProtocol)!);

let src = [
"var wb = XLSX.read(payload, {type:'binary'});",
"var ws = wb.Sheets[wb.SheetNames[0]];",
"var result = XLSX.utils.sheet_to_csv(ws);"
].joined(separator: "\n");
self.context.evaluateScript(src);

return context.objectForKeyedSubscript("result").toString();
}

init() throws {
do {
self.context = try init_context();
self.XLSX = context.objectForKeyedSubscript("XLSX");
if self.XLSX == nil {
throw SheetJS.SJSError.badJSContext;
}
} catch { print(error.localizedDescription); }
}
}

let sheetjs = try SheetJS();
try print(sheetjs.version());
try print(sheetjs.readFileToCSV(file:"sheetjs.xlsx"));
try print(sheetjs.readFileToCSV(file:"sheetjs.xlsb"));
try print(sheetjs.readFileToCSV(file:"sheetjs.xls"));
try print(sheetjs.readFileToCSV(file:"sheetjs.xml.xls"));
31 changes: 31 additions & 0 deletions demos/altjs/SheetJSRhino.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
import com.sheetjs.SheetJS;
import com.sheetjs.SheetJSFile;
import com.sheetjs.SheetJSSheet;

public class SheetJSRhino {
public static void main(String args[]) throws Exception {
try {
SheetJS sjs = new SheetJS();

/* open file */
SheetJSFile xl = sjs.read_file(args[0]);

/* get sheetnames */
String[] sheetnames = xl.get_sheet_names();
System.err.println(sheetnames[0]);

/* convert to CSV */
SheetJSSheet sheet = xl.get_sheet(0);
String csv = sheet.get_csv();

System.out.println(csv);

} catch(Exception e) {
throw e;
} finally {
SheetJS.close();
}
}
}
51 changes: 51 additions & 0 deletions demos/altjs/com/sheetjs/JSHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
package com.sheetjs;

import java.lang.Integer;
import java.lang.StringBuilder;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.NativeArray;
import org.mozilla.javascript.NativeObject;
import org.mozilla.javascript.Scriptable;

public class JSHelper {
static String read_file(String file) throws IOException {
byte[] b = Files.readAllBytes(Paths.get(file));
System.out.println(b.length);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < b.length; ++i) sb.append(Character.toString((char)b[i]));
return sb.toString();
}

static Object get_object(String path, Object base) throws ObjectNotFoundException {
int idx = path.indexOf(".");
Scriptable b = (Scriptable)base;
if(idx == -1) return b.get(path, b);
Object o = b.get(path.substring(0,idx), b);
if(o == Scriptable.NOT_FOUND) throw new ObjectNotFoundException("not found: |" + path.substring(0,idx) + "|" + Integer.toString(idx));
return get_object(path.substring(idx+1), (NativeObject)o);
}

static Object[] get_array(String path, Object base) throws ObjectNotFoundException {
NativeArray arr = (NativeArray)get_object(path, base);
Object[] out = new Object[(int)arr.getLength()];
int idx;
for(Object o : arr.getIds()) out[idx = (Integer)o] = arr.get(idx, arr);
return out;
}

static String[] get_string_array(String path, Object base) throws ObjectNotFoundException {
NativeArray arr = (NativeArray)get_object(path, base);
String[] out = new String[(int)arr.getLength()];
int idx;
for(Object o : arr.getIds()) out[idx = (Integer)o] = arr.get(idx, arr).toString();
return out;
}

public static void close() { Context.exit(); }

}
10 changes: 10 additions & 0 deletions demos/altjs/com/sheetjs/ObjectNotFoundException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
package com.sheetjs;

import java.lang.Exception;

public class ObjectNotFoundException extends Exception {
public ObjectNotFoundException() {}
public ObjectNotFoundException(String message) { super(message); }
}
58 changes: 58 additions & 0 deletions demos/altjs/com/sheetjs/SheetJS.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
package com.sheetjs;

import java.lang.Integer;
import java.util.Scanner;
import java.io.IOException;
import java.io.File;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.NativeObject;
import org.mozilla.javascript.Scriptable;

public class SheetJS {
public Scriptable scope;
public Context cx;
public NativeObject nXLSX;

public SheetJS() throws Exception {
this.cx = Context.enter();
this.scope = this.cx.initStandardObjects();

/* boilerplate */
cx.setOptimizationLevel(-1);
String s = "var global = (function(){ return this; }).call(null);";
cx.evaluateString(scope, s, "<cmd>", 1, null);

/* eval library */
s = new Scanner(SheetJS.class.getResourceAsStream("/dist/xlsx.full.min.js")).useDelimiter("\\Z").next();
//s = new Scanner(new File("xlsx.full.min.js")).useDelimiter("\\Z").next();
cx.evaluateString(scope, s, "<cmd>", 1, null);

/* grab XLSX variable */
Object XLSX = scope.get("XLSX", scope);
if(XLSX == Scriptable.NOT_FOUND) throw new Exception("XLSX not found");
this.nXLSX = (NativeObject)XLSX;
}

public SheetJSFile read_file(String filename) throws IOException, ObjectNotFoundException {
/* open file */
String d = JSHelper.read_file(filename);

/* options argument */
NativeObject q = (NativeObject)this.cx.evaluateString(this.scope, "q = {'type':'binary'};", "<cmd>", 2, null);

/* set up function arguments */
Object functionArgs[] = {d, q};

/* call read -> wb workbook */
Function readfunc = (Function)JSHelper.get_object("XLSX.read",this.scope);
NativeObject wb = (NativeObject)readfunc.call(this.cx, this.scope, this.nXLSX, functionArgs);

return new SheetJSFile(wb, this);
}

public static void close() { JSHelper.close(); }
}

Loading

0 comments on commit ad47cb4

Please sign in to comment.