opal 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -10
- data/LICENSE +75 -0
- data/README.md +55 -3
- data/Rakefile +62 -139
- data/bin/opal +7 -10
- data/gems/core/README.md +5 -0
- data/gems/core/Rakefile +7 -0
- data/gems/core/core.gemspec +13 -0
- data/gems/core/lib/core.rb +33 -0
- data/gems/core/lib/core/array.rb +1470 -0
- data/gems/core/lib/core/basic_object.rb +15 -0
- data/gems/core/lib/core/class.rb +31 -0
- data/gems/core/lib/core/dir.rb +26 -0
- data/gems/core/lib/core/error.rb +43 -0
- data/gems/core/lib/core/false_class.rb +21 -0
- data/gems/core/lib/core/file.rb +54 -0
- data/gems/core/lib/core/hash.rb +725 -0
- data/gems/core/lib/core/kernel.rb +240 -0
- data/gems/core/lib/core/module.rb +98 -0
- data/gems/core/lib/core/nil_class.rb +41 -0
- data/gems/core/lib/core/numeric.rb +370 -0
- data/gems/core/lib/core/proc.rb +11 -0
- data/gems/core/lib/core/range.rb +17 -0
- data/gems/core/lib/core/regexp.rb +18 -0
- data/gems/core/lib/core/string.rb +328 -0
- data/gems/core/lib/core/symbol.rb +15 -0
- data/gems/core/lib/core/top_self.rb +8 -0
- data/gems/core/lib/core/true_class.rb +20 -0
- data/gems/core/lib/core/vm.rb +16 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/append_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/assoc_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/at_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/clear_spec.rb +1 -1
- data/{opals/opal/opal → gems/core}/spec/core/array/collect_bang_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/collect_spec.rb +0 -0
- data/gems/core/spec/core/array/compact_spec.rb +41 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/concat_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/constructor_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/each_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/element_reference_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/first_spec.rb +1 -1
- data/{opals/opal/opal → gems/core}/spec/core/array/include_spec.rb +0 -0
- data/gems/core/spec/core/array/join_spec.rb +6 -0
- data/gems/core/spec/core/array/last_spec.rb +51 -0
- data/gems/core/spec/core/array/length_spec.rb +6 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/map_spec.rb +2 -0
- data/gems/core/spec/core/array/reverse_spec.rb +6 -0
- data/{opals/opal/opal → gems/core}/spec/core/builtin_constants/builtin_constants_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/false/and_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/false/inspect_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/false/or_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/false/to_s_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/false/xor_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/file/join_spec.rb +1 -1
- data/gems/core/spec/core/hash/assoc_spec.rb +32 -0
- data/{opals/opal/opal → gems/core}/spec/core/kernel/instance_eval_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/kernel/loop_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/kernel/raise_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/module/attr_accessor_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/number/lt_spec.rb +0 -0
- data/gems/core/spec/core/string/sub_spec.rb +24 -0
- data/{opals/opal/opal → gems/core}/spec/core/true/and_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/true/inspect_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/true/or_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/true/to_s_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/true/xor_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/and_spec.rb +2 -3
- data/{opals/opal/opal → gems/core}/spec/language/array_spec.rb +21 -5
- data/gems/core/spec/language/block_spec.rb +38 -0
- data/{opals/opal/opal → gems/core}/spec/language/break_spec.rb +0 -0
- data/gems/core/spec/language/case_spec.rb +103 -0
- data/{opals/opal/opal → gems/core}/spec/language/def_spec.rb +11 -1
- data/{opals/opal/opal → gems/core}/spec/language/eigenclass_spec.rb +0 -0
- data/gems/core/spec/language/file_spec.rb +13 -0
- data/gems/core/spec/language/fixtures/block.rb +21 -0
- data/gems/core/spec/language/fixtures/super.rb +293 -0
- data/{opals/opal/opal → gems/core}/spec/language/hash_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/if_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/loop_spec.rb +0 -0
- data/gems/core/spec/language/metaclass_spec.rb +21 -0
- data/{opals/opal/opal → gems/core}/spec/language/method_spec.rb +60 -0
- data/{opals/opal/opal → gems/core}/spec/language/next_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/or_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/redo_spec.rb +0 -0
- data/gems/core/spec/language/regexp_spec.rb +26 -0
- data/{opals/opal/opal → gems/core}/spec/language/rescue_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/return_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/string_spec.rb +0 -0
- data/gems/core/spec/language/super_spec.rb +32 -0
- data/{opals/opal/opal → gems/core}/spec/language/until_spec.rb +47 -47
- data/gems/core/spec/language/variables_spec.rb +155 -0
- data/{opals/opal/opal → gems/core}/spec/language/while_spec.rb +47 -47
- data/{opals/opal/opal → gems/core}/spec/spec_helper.rb +1 -1
- data/gems/core_fs/README.md +19 -0
- data/gems/dev/Rakefile +5 -0
- data/gems/dev/lib/dev.js +99 -0
- data/gems/dev/lib/dev/generator.js +1264 -0
- data/gems/dev/lib/dev/parser.js +979 -0
- data/gems/dev/lib/dev/ruby_parser.js +1088 -0
- data/gems/dev/lib/dev/ruby_parser.y +1267 -0
- data/gems/dev/lib/dev/string_scanner.js +38 -0
- data/gems/dev/tools/racc2js/README.md +39 -0
- data/gems/dev/tools/racc2js/math_parser.js +222 -0
- data/gems/dev/tools/racc2js/math_parser.rb +133 -0
- data/gems/dev/tools/racc2js/math_parser.y +28 -0
- data/gems/dev/tools/racc2js/parser.js +218 -0
- data/gems/dev/tools/racc2js/racc2js.rb +153 -0
- data/gems/json/README.md +4 -0
- data/gems/json/json.gemspec +14 -0
- data/gems/json/lib/json.rb +64 -0
- data/gems/json/lib/json/ext.rb +51 -0
- data/{opals/opal/browser/lib/browser/json_parse.js → gems/json/lib/json/json2.js} +197 -37
- data/gems/ospec/README.md +0 -0
- data/gems/ospec/lib/ospec.rb +6 -0
- data/gems/ospec/lib/ospec/autorun.rb +3 -0
- data/gems/ospec/lib/ospec/dsl.rb +15 -0
- data/gems/ospec/lib/ospec/example.rb +11 -0
- data/gems/ospec/lib/ospec/example/before_and_after_hooks.rb +56 -0
- data/gems/ospec/lib/ospec/example/errors.rb +17 -0
- data/gems/ospec/lib/ospec/example/example_group.rb +12 -0
- data/gems/ospec/lib/ospec/example/example_group_factory.rb +21 -0
- data/gems/ospec/lib/ospec/example/example_group_hierarchy.rb +20 -0
- data/{opals/opal/spec/lib/spec → gems/ospec/lib/ospec}/example/example_group_methods.rb +26 -68
- data/gems/ospec/lib/ospec/example/example_group_proxy.rb +14 -0
- data/gems/ospec/lib/ospec/example/example_methods.rb +46 -0
- data/gems/ospec/lib/ospec/example/example_proxy.rb +18 -0
- data/gems/ospec/lib/ospec/expectations.rb +19 -0
- data/gems/ospec/lib/ospec/expectations/errors.rb +8 -0
- data/gems/ospec/lib/ospec/expectations/fail_with.rb +8 -0
- data/gems/ospec/lib/ospec/expectations/handler.rb +27 -0
- data/gems/ospec/lib/ospec/matchers.rb +24 -0
- data/{opals/opal/Rakefile → gems/ospec/lib/ospec/matchers/be.rb} +0 -0
- data/gems/ospec/lib/ospec/matchers/generated_descriptions.rb +20 -0
- data/gems/ospec/lib/ospec/matchers/operator_matcher.rb +52 -0
- data/gems/ospec/lib/ospec/runner.rb +40 -0
- data/gems/ospec/lib/ospec/runner/example_group_runner.rb +44 -0
- data/{opals/opal/spec/lib/spec → gems/ospec/lib/ospec}/runner/formatter/html_formatter.rb +31 -40
- data/gems/ospec/lib/ospec/runner/formatter/terminal_formatter.rb +48 -0
- data/gems/ospec/lib/ospec/runner/options.rb +36 -0
- data/{opals/opal/spec/lib/spec → gems/ospec/lib/ospec}/runner/reporter.rb +23 -55
- data/gems/ospec/ospec.gemspec +0 -0
- data/gems/rquery/README.md +9 -0
- data/gems/rquery/lib/rquery.rb +10 -0
- data/gems/rquery/lib/rquery/ajax.rb +4 -0
- data/gems/rquery/lib/rquery/css.rb +96 -0
- data/gems/rquery/lib/rquery/document.rb +25 -0
- data/gems/rquery/lib/rquery/element.rb +292 -0
- data/gems/rquery/lib/rquery/event.rb +108 -0
- data/gems/rquery/lib/rquery/jquery.js +8177 -0
- data/gems/rquery/lib/rquery/request.rb +138 -0
- data/gems/rquery/lib/rquery/response.rb +49 -0
- data/gems/rquery/rquery.gemspec +16 -0
- data/lib/opal.js +1597 -0
- data/lib/opal.rb +6 -69
- data/lib/opal/builder.rb +115 -0
- data/lib/opal/bundle.rb +131 -0
- data/lib/opal/command.rb +11 -0
- data/lib/opal/context.rb +69 -0
- data/lib/opal/context/console.rb +12 -0
- data/lib/opal/context/file_system.rb +19 -0
- data/lib/opal/context/loader.rb +117 -0
- data/lib/opal/gem.rb +153 -0
- data/lib/opal/ruby/nodes.rb +1302 -0
- data/lib/opal/ruby/parser.rb +780 -0
- data/lib/opal/ruby/ruby_parser.rb +5170 -0
- data/lib/opal/ruby/ruby_parser.y +1298 -0
- data/opal.gemspec +11 -256
- metadata +179 -240
- data/.gitmodules +0 -6
- data/Opalfile +0 -384
- data/VERSION +0 -1
- data/demos/apps/browser_demo/index.html +0 -11
- data/demos/apps/browser_demo/lib/browser_demo.rb +0 -31
- data/demos/apps/simple_opal/Opalfile +0 -13
- data/demos/apps/simple_opal/index.html +0 -11
- data/demos/apps/simple_opal/lib/app_controller.rb +0 -62
- data/demos/apps/simple_opal/lib/main_window.rb +0 -146
- data/demos/browser/request/index.html +0 -52
- data/demos/browser/request/request.rb +0 -48
- data/gen/browser/__PROJECT_NAME__/Rakefile +0 -12
- data/gen/browser/__PROJECT_NAME__/index.html +0 -11
- data/gen/browser/__PROJECT_NAME__/javascripts/opal.debug.js +0 -4687
- data/gen/browser/__PROJECT_NAME__/javascripts/opal.min.js +0 -175
- data/gen/browser/__PROJECT_NAME__/lib/__PROJECT_NAME__.rb +0 -1
- data/lib/opal/builders/base.rb +0 -50
- data/lib/opal/builders/css.rb +0 -46
- data/lib/opal/builders/javascript.rb +0 -44
- data/lib/opal/builders/opal.rb +0 -79
- data/lib/opal/builders/ruby.rb +0 -50
- data/lib/opal/builders/ruby/generate.rb +0 -1851
- data/lib/opal/builders/ruby/nodes.rb +0 -210
- data/lib/opal/builders/ruby/ruby.rb +0 -916
- data/lib/opal/builders/ruby/ruby_parser.rb +0 -6008
- data/lib/opal/builders/ruby/ruby_parser.rb.y +0 -1451
- data/lib/opal/models/build_item.rb +0 -104
- data/lib/opal/models/hash_struct.rb +0 -40
- data/lib/opal/models/project.rb +0 -252
- data/lib/opal/models/struct_accessors.rb +0 -58
- data/lib/opal/models/target.rb +0 -176
- data/lib/opal/opal/build.rb +0 -169
- data/lib/opal/opal/env/console.rb +0 -66
- data/lib/opal/opal/env/fs.rb +0 -98
- data/lib/opal/opal/env/object.rb +0 -48
- data/lib/opal/opal/environment.rb +0 -139
- data/lib/opal/opal/gen.rb +0 -62
- data/lib/opal/opal/opal.rb +0 -75
- data/lib/opal/opal/repl.rb +0 -38
- data/lib/opal/opalfile/dsl.rb +0 -62
- data/lib/opal/opalfile/opalfile.rb +0 -133
- data/lib/opal/opalfile/task.rb +0 -96
- data/lib/opal/opalfile/task_manager.rb +0 -63
- data/lib/opal/opalfile/task_scope.rb +0 -52
- data/lib/opal/rack/app_server.rb +0 -119
- data/lib/opal/rake/opal_task.rb +0 -34
- data/opals/opal/README.md +0 -37
- data/opals/opal/browser/Opalfile +0 -11
- data/opals/opal/browser/README.md +0 -146
- data/opals/opal/browser/SIZZLE_LICESNSE.txt +0 -148
- data/opals/opal/browser/lib/browser.rb +0 -118
- data/opals/opal/browser/lib/browser/builder.rb +0 -41
- data/opals/opal/browser/lib/browser/canvas_context.rb +0 -115
- data/opals/opal/browser/lib/browser/dimensions.rb +0 -50
- data/opals/opal/browser/lib/browser/document.rb +0 -146
- data/opals/opal/browser/lib/browser/element.rb +0 -487
- data/opals/opal/browser/lib/browser/element/attributes.rb +0 -88
- data/opals/opal/browser/lib/browser/element/css.rb +0 -290
- data/opals/opal/browser/lib/browser/element/form.rb +0 -146
- data/opals/opal/browser/lib/browser/event/dom_events.rb +0 -81
- data/opals/opal/browser/lib/browser/event/event.rb +0 -177
- data/opals/opal/browser/lib/browser/event/trigger_events.rb +0 -53
- data/opals/opal/browser/lib/browser/geometry.rb +0 -97
- data/opals/opal/browser/lib/browser/json.rb +0 -32
- data/opals/opal/browser/lib/browser/request/request.rb +0 -201
- data/opals/opal/browser/lib/browser/sizzle.js +0 -1068
- data/opals/opal/browser/lib/browser/string.rb +0 -42
- data/opals/opal/browser/lib/browser/touch.rb +0 -37
- data/opals/opal/browser/lib/browser/vml_context.js +0 -33
- data/opals/opal/browser/lib/browser/window.rb +0 -36
- data/opals/opal/browser/spec/browser/browser_detection_spec.rb +0 -7
- data/opals/opal/browser/spec/document/aref_spec.rb +0 -110
- data/opals/opal/browser/spec/document/ready_spec.rb +0 -16
- data/opals/opal/browser/spec/element/body_spec.rb +0 -11
- data/opals/opal/browser/spec/element/clear_spec.rb +0 -26
- data/opals/opal/browser/spec/element/empty_spec.rb +0 -29
- data/opals/opal/browser/spec/element/has_class_spec.rb +0 -40
- data/opals/opal/browser/spec/element/hidden_spec.rb +0 -23
- data/opals/opal/browser/spec/element/hide_spec.rb +0 -31
- data/opals/opal/browser/spec/element/remove_spec.rb +0 -25
- data/opals/opal/browser/spec/element/show_spec.rb +0 -31
- data/opals/opal/browser/spec/element/style_spec.rb +0 -69
- data/opals/opal/browser/spec/element/toggle_spec.rb +0 -31
- data/opals/opal/browser/spec/element/visible_spec.rb +0 -23
- data/opals/opal/browser/spec/spec_helper.rb +0 -1
- data/opals/opal/opal/Opalfile +0 -14
- data/opals/opal/opal/spec/core/array/compact_spec.rb +0 -15
- data/opals/opal/opal/spec/fixtures/super.rb +0 -70
- data/opals/opal/opal/spec/language/____temp_remove_this.rb +0 -12
- data/opals/opal/opal/spec/language/block_spec.rb +0 -18
- data/opals/opal/opal/spec/language/case_spec.rb +0 -103
- data/opals/opal/opal/spec/language/metaclass_spec.rb +0 -21
- data/opals/opal/opal/spec/language/super_spec.rb +0 -26
- data/opals/opal/runtime/Opalfile +0 -78
- data/opals/opal/runtime/README.md +0 -12
- data/opals/opal/runtime/docs/debugging.md +0 -51
- data/opals/opal/runtime/lib/array.rb +0 -1516
- data/opals/opal/runtime/lib/basic_object.rb +0 -49
- data/opals/opal/runtime/lib/class.rb +0 -54
- data/opals/opal/runtime/lib/dir.rb +0 -36
- data/opals/opal/runtime/lib/error.rb +0 -49
- data/opals/opal/runtime/lib/false_class.rb +0 -52
- data/opals/opal/runtime/lib/file.rb +0 -79
- data/opals/opal/runtime/lib/hash.rb +0 -791
- data/opals/opal/runtime/lib/io.rb +0 -39
- data/opals/opal/runtime/lib/kernel.rb +0 -288
- data/opals/opal/runtime/lib/match_data.rb +0 -36
- data/opals/opal/runtime/lib/module.rb +0 -109
- data/opals/opal/runtime/lib/nil_class.rb +0 -69
- data/opals/opal/runtime/lib/number.rb +0 -398
- data/opals/opal/runtime/lib/proc.rb +0 -77
- data/opals/opal/runtime/lib/range.rb +0 -63
- data/opals/opal/runtime/lib/regexp.rb +0 -111
- data/opals/opal/runtime/lib/ruby.rb +0 -30
- data/opals/opal/runtime/lib/string.rb +0 -328
- data/opals/opal/runtime/lib/symbol.rb +0 -40
- data/opals/opal/runtime/lib/top_self.rb +0 -33
- data/opals/opal/runtime/lib/true_class.rb +0 -45
- data/opals/opal/runtime/runtime/browser.js +0 -287
- data/opals/opal/runtime/runtime/debug.js +0 -180
- data/opals/opal/runtime/runtime/opal.js +0 -1008
- data/opals/opal/runtime/runtime/post_opal.js +0 -1
- data/opals/opal/runtime/runtime/pre_opal.js +0 -2
- data/opals/opal/runtime/runtime/server_side.js +0 -50
- data/opals/opal/spec/LICENSE.txt +0 -26
- data/opals/opal/spec/Opalfile +0 -5
- data/opals/opal/spec/bin/spec.rb +0 -43
- data/opals/opal/spec/lib/spec.rb +0 -33
- data/opals/opal/spec/lib/spec/dsl.rb +0 -41
- data/opals/opal/spec/lib/spec/example.rb +0 -35
- data/opals/opal/spec/lib/spec/example/before_and_after_hooks.rb +0 -81
- data/opals/opal/spec/lib/spec/example/errors.rb +0 -42
- data/opals/opal/spec/lib/spec/example/example_group.rb +0 -37
- data/opals/opal/spec/lib/spec/example/example_group_factory.rb +0 -43
- data/opals/opal/spec/lib/spec/example/example_group_hierarchy.rb +0 -45
- data/opals/opal/spec/lib/spec/example/example_group_proxy.rb +0 -41
- data/opals/opal/spec/lib/spec/example/example_methods.rb +0 -73
- data/opals/opal/spec/lib/spec/example/example_proxy.rb +0 -48
- data/opals/opal/spec/lib/spec/expectations.rb +0 -46
- data/opals/opal/spec/lib/spec/expectations/errors.rb +0 -35
- data/opals/opal/spec/lib/spec/expectations/fail_with.rb +0 -37
- data/opals/opal/spec/lib/spec/expectations/handler.rb +0 -48
- data/opals/opal/spec/lib/spec/matchers.rb +0 -50
- data/opals/opal/spec/lib/spec/matchers/be.rb +0 -26
- data/opals/opal/spec/lib/spec/matchers/generated_descriptions.rb +0 -47
- data/opals/opal/spec/lib/spec/matchers/operator_matcher.rb +0 -66
- data/opals/opal/spec/lib/spec/runner.rb +0 -48
- data/opals/opal/spec/lib/spec/runner/example_group_runner.rb +0 -71
- data/opals/opal/spec/lib/spec/runner/formatter/terminal_formatter.rb +0 -82
- data/opals/opal/spec/lib/spec/runner/options.rb +0 -63
- data/opals/opal/spec/resources/index.html +0 -25
- data/opals/opal/spec/resources/spec.css +0 -132
- data/spec/cherry_kit/iseq_spec.rb +0 -38
- data/spec/spec_helper.rb +0 -16
- data/spec/vienna_spec.rb +0 -7
- data/yard/index.html +0 -43
- data/yard/style.css +0 -765
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# The Request class wraps the native XMLHttpRequest object in the
|
|
2
|
+
# browser and makes use of jQuery's ajax facilities to make requests.
|
|
3
|
+
class Request
|
|
4
|
+
|
|
5
|
+
# Default options used by all Requests. Unless an option here is
|
|
6
|
+
# overrideen, then these defaults will be used on each request. This
|
|
7
|
+
# is not a full list of all options that can be used; these are just
|
|
8
|
+
# the bare essentials and useful defaults.
|
|
9
|
+
DEFAULT_OPTIONS = {
|
|
10
|
+
:url => '',
|
|
11
|
+
:type => 'GET'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
# Creates a new Request object. The passed options are merged with
|
|
15
|
+
# DEFAULT_OPTIONS and will be used as the base options for each
|
|
16
|
+
# request. Request specific options may be passed to {#send}, and
|
|
17
|
+
# these will be used in preference to the options passed here.
|
|
18
|
+
#
|
|
19
|
+
# Most of the options that can be set also have their own designated
|
|
20
|
+
# getters and setters as instance methods on this class. This allows
|
|
21
|
+
# for options to be set in a more independant manner instead of
|
|
22
|
+
# collecting all options into the initialization hash.
|
|
23
|
+
#
|
|
24
|
+
# @param [Hash] options request options
|
|
25
|
+
# @return [Request] returns new request instance
|
|
26
|
+
def initialize(options = {})
|
|
27
|
+
@options = DEFAULT_OPTIONS.merge options
|
|
28
|
+
@complete_action = nil
|
|
29
|
+
@failure_action = nil
|
|
30
|
+
@success_action = nil
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Creates attribute reader and writers for the given options that will
|
|
34
|
+
# set/retrieve the values from the options hash belonging to this
|
|
35
|
+
# instance. Each of these options may also be overriden by the final
|
|
36
|
+
# values sent to {#send}, or one of its aliases: {#get}, {#post},
|
|
37
|
+
# {#put} or {#delete}.
|
|
38
|
+
#
|
|
39
|
+
# @param [String, Symbol] names option names to set
|
|
40
|
+
def self.option_accessor(*names)
|
|
41
|
+
names.each do |name|
|
|
42
|
+
# define option getter
|
|
43
|
+
define_method(name) { @options[name] }
|
|
44
|
+
# define option setter
|
|
45
|
+
define_method("#{name}=") { |value| @options[name] = value }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# By default all requests will be sent async, to avoid locking up the
|
|
50
|
+
# browser. Set this to `false` to send requests in a sync fashion.
|
|
51
|
+
# This defaults to `true` to send by async by default.
|
|
52
|
+
option_accessor :async
|
|
53
|
+
|
|
54
|
+
# Gets the type of the request, which is "GET" by default. This value
|
|
55
|
+
# may be "GET" or "POST", as they are well supported by the browser,
|
|
56
|
+
# but "PUT" and "DELETE" may also be used, but they are not supported
|
|
57
|
+
# within the browser.
|
|
58
|
+
option_accessor :type
|
|
59
|
+
|
|
60
|
+
# Holds the string representing the URL to which the request is sent.
|
|
61
|
+
# By default this is an empty string, so it needs to be set to get any
|
|
62
|
+
# useful requests back.
|
|
63
|
+
option_accessor :url
|
|
64
|
+
|
|
65
|
+
# Sets the username to use when accessing the HTTP authentication
|
|
66
|
+
# requests.
|
|
67
|
+
option_accessor :username
|
|
68
|
+
|
|
69
|
+
# Sets the relevant password used in the HTTP authentication requests.
|
|
70
|
+
option_accessor :password
|
|
71
|
+
|
|
72
|
+
# Sends the request with the specified options. These options are
|
|
73
|
+
# merged with the options given to {#initialize}. There are also
|
|
74
|
+
# aliases for this method for automatically setting the request
|
|
75
|
+
# type; {#put}, {#post}, {#get} and {#delete} will automatically
|
|
76
|
+
# set the correct request type to avoid the need to set it in the
|
|
77
|
+
# options.
|
|
78
|
+
#
|
|
79
|
+
# @param [Hash] options the request options
|
|
80
|
+
# @return [Request] returns the receiver
|
|
81
|
+
def send(options = {})
|
|
82
|
+
`options = #{@options.merge options};
|
|
83
|
+
|
|
84
|
+
// native options object
|
|
85
|
+
var opts = {};
|
|
86
|
+
|
|
87
|
+
// we must have a url
|
|
88
|
+
opts.url = #{options[:url]}
|
|
89
|
+
|
|
90
|
+
// request type
|
|
91
|
+
opts.type = #{options[:type]}
|
|
92
|
+
|
|
93
|
+
// success callback
|
|
94
|
+
if (#{@success_action} != nil) {
|
|
95
|
+
opts.success = function(data, textStatus, jqXHR) {
|
|
96
|
+
var response = #{Response.new `jqXHR`};
|
|
97
|
+
#{@success_action.call `response`};
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
$.ajax(opts);
|
|
102
|
+
|
|
103
|
+
return self;`
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def get(options = {})
|
|
107
|
+
options[:type] = 'GET'
|
|
108
|
+
send options
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def post(options = {})
|
|
112
|
+
options[:type] = 'POST'
|
|
113
|
+
send options
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def put(options = {})
|
|
117
|
+
options[:type] = 'PUT'
|
|
118
|
+
send options
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def delete(options = {})
|
|
122
|
+
options[:type] = 'DELETE'
|
|
123
|
+
send options
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Register a block that will be called if the request succeeds.
|
|
127
|
+
def success(&block)
|
|
128
|
+
@success_action = block
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Register a block that will be called if the request fails
|
|
132
|
+
|
|
133
|
+
def failure(&block)
|
|
134
|
+
@failure_action = block
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Instances of Response are automatically created by Request, so you do
|
|
2
|
+
# not need to make them yourself. This is the object that will be passed
|
|
3
|
+
# to each of the callbacks for a Request object. For this reason, this
|
|
4
|
+
# object will be created if the request succeeds, or indeed fails.
|
|
5
|
+
class Response
|
|
6
|
+
# Private initializer. This handles a native jquery requets object, so
|
|
7
|
+
# this should all probably be private.
|
|
8
|
+
def initialize(request)
|
|
9
|
+
`self.$xhr = request`
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Returns the numeric status code for the response.
|
|
13
|
+
#
|
|
14
|
+
# @return [Numeric]
|
|
15
|
+
def status
|
|
16
|
+
`return self.$xhr.status;`
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Returns the string status message for the response.
|
|
20
|
+
#
|
|
21
|
+
# @return [String]
|
|
22
|
+
def status_text
|
|
23
|
+
`return self.$xhr.statusText;`
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Returns the response text from the request.
|
|
27
|
+
#
|
|
28
|
+
# @return [String]
|
|
29
|
+
def text
|
|
30
|
+
`return self.$xhr.responseText;`
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Returns `true` if the response represents a successfull request,
|
|
34
|
+
# `false` otherwise.
|
|
35
|
+
#
|
|
36
|
+
# @return [true, false]
|
|
37
|
+
def success?
|
|
38
|
+
`return (self.$xhr.status >= 200 && self.$xhr.status < 300) ? Qtrue : Qfalse;`
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Returns `false` if the response was the result of an unsuccessful
|
|
42
|
+
# request, `true` otherwise.
|
|
43
|
+
#
|
|
44
|
+
# @return [true, false]
|
|
45
|
+
def failure?
|
|
46
|
+
!success?
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |s|
|
|
4
|
+
s.name = "rquery"
|
|
5
|
+
s.version = "0.0.1"
|
|
6
|
+
s.authors = ["Adam Beynon"]
|
|
7
|
+
s.email = ["adam@adambeynon.com"]
|
|
8
|
+
s.homepage = "http://github.com/adambeynon/opal"
|
|
9
|
+
s.summary = "Rquery DOM library for ruby/opal"
|
|
10
|
+
|
|
11
|
+
s.files = Dir.glob("{bin,lib}/**/*") + %w[README.md]
|
|
12
|
+
s.require_path = "lib"
|
|
13
|
+
|
|
14
|
+
s.add_dependency "json"
|
|
15
|
+
end
|
|
16
|
+
|
data/lib/opal.js
ADDED
|
@@ -0,0 +1,1597 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Incase we are in browser, wrap body to avoid global vars. Just opal can become
|
|
3
|
+
a top level var. We treat opal as our exports in nodejs, as we reassign them
|
|
4
|
+
at the bottom of this file.
|
|
5
|
+
*/
|
|
6
|
+
var opal = {};
|
|
7
|
+
|
|
8
|
+
(function() {
|
|
9
|
+
|
|
10
|
+
// So we can minimize
|
|
11
|
+
var Op = opal;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
Core runtime classes, objects and literals.
|
|
15
|
+
*/
|
|
16
|
+
var cBasicObject, cObject, cModule, cClass,
|
|
17
|
+
mKernel, cNilClass, cTrueClass, cFalseClass,
|
|
18
|
+
cFile, cProc, cNumeric, cArray,
|
|
19
|
+
cHash, cString, cSymbol, cRange,
|
|
20
|
+
cRegexp, cMatch, Qself, Qnil,
|
|
21
|
+
Qfalse, Qtrue;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
Exception classes. Some of these are used by runtime so they are here for
|
|
25
|
+
convenience.
|
|
26
|
+
*/
|
|
27
|
+
var eException, eStandardError, eLocalJumpError, eNameError,
|
|
28
|
+
eNoMethodError, eArgError, eScriptError, eLoadError,
|
|
29
|
+
eRuntimeError, eTypeError, eIndexError, eKeyError,
|
|
30
|
+
eRangeError;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
Standard jump exceptions to save re-creating them everytime they are needed
|
|
34
|
+
*/
|
|
35
|
+
var rb_vm_return_instance,
|
|
36
|
+
rb_vm_loop_return_instance,
|
|
37
|
+
rb_vm_next_instance,
|
|
38
|
+
rb_vm_break_instance;
|
|
39
|
+
|
|
40
|
+
// ..........................................................
|
|
41
|
+
// VIRTUAL MACHINE
|
|
42
|
+
//
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
This is the VM param that gets given to all files in opal. This contains
|
|
46
|
+
just the VM methods for opal, to keep the global opal namespace cleaner as
|
|
47
|
+
it is used just for external access.
|
|
48
|
+
*/
|
|
49
|
+
Op.vm = {};
|
|
50
|
+
|
|
51
|
+
// for minimizng
|
|
52
|
+
var Vm = Op.vm;
|
|
53
|
+
Vm.opal = Op;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
Core object type flags. Added as local variables, and onto Opal prototype.
|
|
57
|
+
*/
|
|
58
|
+
var T_CLASS = Vm.T_CLASS = 1,
|
|
59
|
+
T_MODULE = Vm.T_MODULE = 2,
|
|
60
|
+
T_OBJECT = Vm.T_OBJECT = 4,
|
|
61
|
+
T_BOOLEAN = Vm.T_BOOLEAN = 8,
|
|
62
|
+
T_STRING = Vm.T_STRING = 16,
|
|
63
|
+
T_ARRAY = Vm.T_ARRAY = 32,
|
|
64
|
+
T_NUMBER = Vm.T_NUMBER = 64,
|
|
65
|
+
T_PROC = Vm.T_PROC = 128,
|
|
66
|
+
T_SYMBOL = Vm.T_SYMBOL = 256,
|
|
67
|
+
T_HASH = Vm.T_HASH = 512,
|
|
68
|
+
T_RANGE = Vm.T_RANGE = 1024,
|
|
69
|
+
T_ICLASS = Vm.T_ICLASS = 2056,
|
|
70
|
+
FL_SINGLETON = Vm.FL_SINGLETON = 4112;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
For setting up method_missing methods. Each ruby file that has been compiled
|
|
74
|
+
with call this method with an array of all method_ids that it makes use of.
|
|
75
|
+
These only need to be from method calls. This allows us to make sure this
|
|
76
|
+
method exists on the base prototype, and is set to simply call method_missing
|
|
77
|
+
for the receiver. This adds overhead to the beginning of each file being
|
|
78
|
+
loaded, but is more more efficient than having to check for method_missing on
|
|
79
|
+
every method call in the file for the entirety of its lifetime.
|
|
80
|
+
|
|
81
|
+
@param {Array<String>} method_ids An array of method_ids to register
|
|
82
|
+
*/
|
|
83
|
+
Vm.mm = function(method_ids) {
|
|
84
|
+
var prototype = cBasicObject.$m_prototype_tbl;
|
|
85
|
+
|
|
86
|
+
for (var i = 0, ii = method_ids.length; i < ii; i++) {
|
|
87
|
+
var method_id = method_ids[i];
|
|
88
|
+
// only add fake method if not already defined
|
|
89
|
+
if (!prototype.hasOwnProperty(method_id)) {
|
|
90
|
+
// our fake method implementation
|
|
91
|
+
var imp = (function(method_id) {
|
|
92
|
+
return function(self) {
|
|
93
|
+
var args = [].slice.call(arguments, 1);
|
|
94
|
+
args.unshift(Vm.Y(method_id));
|
|
95
|
+
args.unshift(self);
|
|
96
|
+
return self.$m.method_missing.apply(null, args);
|
|
97
|
+
};
|
|
98
|
+
})(method_id);
|
|
99
|
+
// mark as a fake method to help respond_to? and send, etc.
|
|
100
|
+
imp.$rbMM = true;
|
|
101
|
+
prototype[method_id] = imp;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
Define methods. Public method for defining a method on the given base.
|
|
108
|
+
|
|
109
|
+
@param {RObject} base The base to define method on
|
|
110
|
+
@param {String} method_id Ruby mid
|
|
111
|
+
@param {Function} body The method implementation
|
|
112
|
+
@param {Boolean} singleton Singleton or Normal method. true for singleton
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
Vm.dm = function(base, method_id, body, singleton) {
|
|
116
|
+
if (singleton) {
|
|
117
|
+
define_singleton_method(base, method_id, body);
|
|
118
|
+
} else {
|
|
119
|
+
// should this instead do a rb_singleton_method?? probably..
|
|
120
|
+
if (base.$flags & T_OBJECT) {
|
|
121
|
+
base = base.$klass;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
define_method(base, method_id, body);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return Qnil;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
Define classes. This is the public API for defining classes, shit classes
|
|
132
|
+
and modules.
|
|
133
|
+
|
|
134
|
+
@param {RObject} base
|
|
135
|
+
@param {RClass} super_class
|
|
136
|
+
@param {String} id
|
|
137
|
+
@param {Function} body
|
|
138
|
+
@param {Number} flag
|
|
139
|
+
*/
|
|
140
|
+
Vm.dc = function(base, super_class, id, body, flag) {
|
|
141
|
+
var klass;
|
|
142
|
+
|
|
143
|
+
switch (flag) {
|
|
144
|
+
case 0:
|
|
145
|
+
if (base.$flags & T_OBJECT) {
|
|
146
|
+
base = class_real(base.$klass);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (super_class == Qnil) {
|
|
150
|
+
super_class = cObject;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
klass = define_class_under(base, id, super_class);
|
|
154
|
+
break;
|
|
155
|
+
|
|
156
|
+
case 1:
|
|
157
|
+
klass = singleton_class(base);
|
|
158
|
+
break;
|
|
159
|
+
|
|
160
|
+
case 2:
|
|
161
|
+
if (base.$flags & T_OBJECT) {
|
|
162
|
+
base = class_real(base.$klass);
|
|
163
|
+
}
|
|
164
|
+
klass = define_module_under(base, id);
|
|
165
|
+
break;
|
|
166
|
+
|
|
167
|
+
default:
|
|
168
|
+
raise(eException, "define_class got a unknown flag " + flag);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return body.call(klass);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
Returns a new RHash instance constructed from the given arguments of
|
|
176
|
+
alternate key, value pairs.
|
|
177
|
+
*/
|
|
178
|
+
Vm.H = function() {
|
|
179
|
+
return new RHash(Array.prototype.slice.call(arguments));
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
Returns a new ruby symbol with the given intern value. Symbols are made
|
|
184
|
+
using the new String() constructor, and just have its klass and method
|
|
185
|
+
table reassigned. This makes dealing with strings/symbols internally
|
|
186
|
+
easier as both can be used as a string within opal.
|
|
187
|
+
|
|
188
|
+
@param {String} intern Symbol value
|
|
189
|
+
@return {RSymbol} symbol
|
|
190
|
+
*/
|
|
191
|
+
Vm.Y = function(intern) {
|
|
192
|
+
if (symbol_table.hasOwnProperty(intern)) {
|
|
193
|
+
return symbol_table[intern];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
var res = new String(intern);
|
|
197
|
+
res.$klass = cSymbol;
|
|
198
|
+
res.$m = cSymbol.$m_tbl;
|
|
199
|
+
symbol_table[intern] = res;
|
|
200
|
+
return res;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
Returns a new ruby range. 'G' for range... yeah.
|
|
205
|
+
|
|
206
|
+
@param {RObject} beg The start item for the range
|
|
207
|
+
@param {RObject} end The finish item for the range
|
|
208
|
+
@param {true, false} exclude_end Whether or not the range excludes the last item
|
|
209
|
+
@return {RRange} Returns the new range instance
|
|
210
|
+
*/
|
|
211
|
+
Vm.G = function(beg, end, exclude_end) {
|
|
212
|
+
return new RRange(beg, end, exclude_end);
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
Ruby break statement with the given value. When no break value is needed, nil
|
|
217
|
+
should be passed here. An undefined/null value is not valid and will cause an
|
|
218
|
+
internal error.
|
|
219
|
+
|
|
220
|
+
@param {RObject} value The break value.
|
|
221
|
+
*/
|
|
222
|
+
Vm.B = function(value) {
|
|
223
|
+
rb_vm_break_instance.$value = value;
|
|
224
|
+
throw rb_vm_break_instance;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
Ruby return, with the given value. The func is the reference function which
|
|
229
|
+
represents the method that this statement must return from.
|
|
230
|
+
*/
|
|
231
|
+
Vm.R = function(value, func) {
|
|
232
|
+
rb_vm_return_instance.$value = value;
|
|
233
|
+
rb_vm_return_instance.$func = func;
|
|
234
|
+
throw rb_vm_return_instance;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
Block passing. This holds the current block info for the runtime.
|
|
239
|
+
|
|
240
|
+
f: function
|
|
241
|
+
p: block
|
|
242
|
+
y: yield error
|
|
243
|
+
|
|
244
|
+
*/
|
|
245
|
+
Vm.P = {
|
|
246
|
+
f: null,
|
|
247
|
+
p: null,
|
|
248
|
+
y: function() {
|
|
249
|
+
throw new Error("LocalJumpError - opal.P.y - no block given");
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
Define a toll free bridged class.
|
|
255
|
+
|
|
256
|
+
@param {Object} prototype Native prototype to extend
|
|
257
|
+
@param {Number} flags The flags for instances of class
|
|
258
|
+
@param {String} id Class id
|
|
259
|
+
@param {RClass} super_klass
|
|
260
|
+
*/
|
|
261
|
+
Vm.bridged_class = function(prototype, flags, id, super_klass) {
|
|
262
|
+
return bridge_class(prototype, flags || T_OBJECT, id, super_klass);
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
Sets the constant value `val` on the given `klass` as `id`.
|
|
267
|
+
|
|
268
|
+
@param {RClass} klass
|
|
269
|
+
@param {String} id
|
|
270
|
+
@param {Object} val
|
|
271
|
+
@return {Object} returns the set value
|
|
272
|
+
*/
|
|
273
|
+
function const_set(klass, id, val) {
|
|
274
|
+
klass.$c_prototype[id] = val;
|
|
275
|
+
return val;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
Lookup a constant named `id` on the `klass`. This will throw an error if
|
|
280
|
+
the constant cannot be found.
|
|
281
|
+
|
|
282
|
+
@param {RClass} klass
|
|
283
|
+
@param {String} id
|
|
284
|
+
*/
|
|
285
|
+
function const_get(klass, id) {
|
|
286
|
+
if (klass.$c[id]) {
|
|
287
|
+
return (klass.$c[id]);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
var parent = klass.$parent;
|
|
291
|
+
|
|
292
|
+
while (parent && parent != cObject) {
|
|
293
|
+
if (parent.$c[id]) {
|
|
294
|
+
return parent.$c[id];
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
parent = parent.$parent;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
raise(eNameError, 'uninitialized constant ' + id);
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
Returns true or false depending whether a constant named `id` is defined
|
|
305
|
+
on the receiver `klass`.
|
|
306
|
+
|
|
307
|
+
@param {RClass} klass
|
|
308
|
+
@param {String} id
|
|
309
|
+
@return {true, false}
|
|
310
|
+
*/
|
|
311
|
+
function const_defined(klass, id) {
|
|
312
|
+
if (klass.$c[id]) {
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return false;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
Set an instance variable on the receiver.
|
|
321
|
+
*/
|
|
322
|
+
function ivar_set(obj, id, val) {
|
|
323
|
+
obj[id] = val;
|
|
324
|
+
return val;
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
Return an instance variable set on the receiver, or nil if one does not
|
|
329
|
+
exist.
|
|
330
|
+
*/
|
|
331
|
+
function ivar_get(obj, id) {
|
|
332
|
+
return obj.hasOwnProperty(id) ? obj[id] : Qnil;
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
Determines whether and instance variable has been set on the receiver.
|
|
337
|
+
*/
|
|
338
|
+
function ivar_defined(obj, id) {
|
|
339
|
+
return obj.hasOwnProperty(id) ? true : false;
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
This table holds all the global variables accessible from ruby.
|
|
344
|
+
|
|
345
|
+
Entries are mapped by their global id => an object that contains the
|
|
346
|
+
given keys:
|
|
347
|
+
|
|
348
|
+
- name
|
|
349
|
+
- value
|
|
350
|
+
- getter
|
|
351
|
+
- setter
|
|
352
|
+
*/
|
|
353
|
+
var global_tbl = {};
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
Defines a hooked/global variable.
|
|
357
|
+
|
|
358
|
+
@param {String} name The global name (e.g. '$:')
|
|
359
|
+
@param {Function} getter The getter function to return the variable
|
|
360
|
+
@param {Function} setter The setter function used for setting the var
|
|
361
|
+
@return {null}
|
|
362
|
+
*/
|
|
363
|
+
function define_hooked_variable(name, getter, setter) {
|
|
364
|
+
var entry = {
|
|
365
|
+
"name": name,
|
|
366
|
+
"value": Qnil,
|
|
367
|
+
"getter": getter,
|
|
368
|
+
"setter": setter
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
global_tbl[name] = entry;
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
A default read only getter for a global variable. This will simply throw a
|
|
376
|
+
name error with the given id. This can be used for variables that should
|
|
377
|
+
not be altered.
|
|
378
|
+
*/
|
|
379
|
+
function gvar_readonly_setter(id, value) {
|
|
380
|
+
raise(eNameError, id + " is a read-only variable");
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
Retrieve a global variable. This will use the assigned getter.
|
|
385
|
+
*/
|
|
386
|
+
function gvar_get(id) {
|
|
387
|
+
var entry = global_tbl[id];
|
|
388
|
+
if (!entry) { return Qnil; }
|
|
389
|
+
return entry.getter(id);
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
Set a global. If not already set, then we assign basic getters and setters.
|
|
394
|
+
*/
|
|
395
|
+
function gvar_set(id, value) {
|
|
396
|
+
var entry = global_tbl[id];
|
|
397
|
+
if (entry) { return entry.setter(id, value); }
|
|
398
|
+
|
|
399
|
+
define_hooked_variable(id,
|
|
400
|
+
|
|
401
|
+
function(id) {
|
|
402
|
+
return global_tbl[id].value;
|
|
403
|
+
},
|
|
404
|
+
|
|
405
|
+
function(id, value) {
|
|
406
|
+
return (global_tbl[id].value = value);
|
|
407
|
+
}
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
return gvar_set(id, value);
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
Every object has a unique id. This count is used as the next id for the
|
|
415
|
+
next created object. Therefore, first ruby object has id 0, next has 1 etc.
|
|
416
|
+
*/
|
|
417
|
+
var hash_yield = 0;
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
Yield the next object id, updating the count, and returning it.
|
|
421
|
+
*/
|
|
422
|
+
function yield_hash() {
|
|
423
|
+
return hash_yield++;
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
The root class. Every class in opal is an instance of RClass.
|
|
428
|
+
|
|
429
|
+
@constructor
|
|
430
|
+
@param {RClass} klass
|
|
431
|
+
@param {RClass} super_klass
|
|
432
|
+
*/
|
|
433
|
+
var RClass = Vm.RClass = function(klass, super_klass) {
|
|
434
|
+
this.$id = yield_hash();
|
|
435
|
+
this.$super = super_klass;
|
|
436
|
+
|
|
437
|
+
if (super_klass) {
|
|
438
|
+
var ctor = function() {};
|
|
439
|
+
ctor.prototype = super_klass.$m_prototype_tbl;
|
|
440
|
+
|
|
441
|
+
var m_ctor = function() {};
|
|
442
|
+
m_ctor.prototype = new ctor();
|
|
443
|
+
|
|
444
|
+
this.$m_tbl = new m_ctor();
|
|
445
|
+
this.$m_prototype_tbl = m_ctor.prototype;
|
|
446
|
+
|
|
447
|
+
var cctor = function() {};
|
|
448
|
+
cctor.prototype = super_klass.$c_prototype;
|
|
449
|
+
|
|
450
|
+
var c_ctor = function() {};
|
|
451
|
+
c_ctor.prototype = new cctor();
|
|
452
|
+
|
|
453
|
+
this.$c = new c_ctor();
|
|
454
|
+
this.$c_prototype = c_ctor.prototype;
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
var m_ctor = function() {};
|
|
458
|
+
this.$m_tbl = new m_ctor();
|
|
459
|
+
this.$m_prototype_tbl = m_ctor.prototype;
|
|
460
|
+
|
|
461
|
+
var c_ctor = function() {};
|
|
462
|
+
this.$c = new c_ctor();
|
|
463
|
+
this.$c_prototype = c_ctor.prototype;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
this.$method_table = {};
|
|
467
|
+
return this;
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
// RClass protoype for minimizing
|
|
471
|
+
var Rp = RClass.prototype;
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
Flags. Every RClass instance is simply a T_CLASS, so mark as so.
|
|
475
|
+
*/
|
|
476
|
+
Rp.$flags = T_CLASS;
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
RTest/truthiness - every RClass instance is true.
|
|
480
|
+
*/
|
|
481
|
+
Rp.$r = true;
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
The root object. Every object in opal (apart from toll free bridged classes
|
|
485
|
+
like array, string etc) are an instance of RObject.
|
|
486
|
+
|
|
487
|
+
@param {RClass} klass
|
|
488
|
+
*/
|
|
489
|
+
var RObject = Vm.RObject = function(klass) {
|
|
490
|
+
this.$id = yield_hash();
|
|
491
|
+
this.$klass = klass;
|
|
492
|
+
this.$m = klass.$m_tbl;
|
|
493
|
+
return this;
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
// For minimizing
|
|
497
|
+
var Bp = RObject.prototype;
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
Flags - every RObject instance is simply a T_OBJECT
|
|
501
|
+
*/
|
|
502
|
+
Bp.$flags = T_OBJECT;
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
RTest - every RObject instance is true.
|
|
506
|
+
*/
|
|
507
|
+
Bp.$r = true;
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
The hash of a class or object in ruby is simply it's id, as all objects and
|
|
511
|
+
classes have unique ids.
|
|
512
|
+
*/
|
|
513
|
+
Bp.$hash = Rp.$hash = function() {
|
|
514
|
+
return this.$id;
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
Internal method for defining a method.
|
|
519
|
+
|
|
520
|
+
@param {RClass} klass The klass to define the method on
|
|
521
|
+
@param {String} name The method id
|
|
522
|
+
@param {Function} body Method implementation
|
|
523
|
+
@return {Qnil}
|
|
524
|
+
*/
|
|
525
|
+
function define_method(klass, name, body) {
|
|
526
|
+
klass.$m_prototype_tbl[name] = body;
|
|
527
|
+
klass.$method_table[name] = body;
|
|
528
|
+
|
|
529
|
+
if (klass.$included_in) {
|
|
530
|
+
for (var i = 0; i < klass.$included_in.length; i++) {
|
|
531
|
+
klass.$included_in[i].$m_prototype_tbl[name] = body;
|
|
532
|
+
klass.$included_in[i].$method_table[name] = body;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
if (!body.$rbName) {
|
|
537
|
+
body.$rbName = name;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
return Qnil;
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
Vm.define_method = define_method;
|
|
544
|
+
|
|
545
|
+
function define_singleton_method(klass, name, body) {
|
|
546
|
+
define_method(singleton_class(klass), name, body);
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
function define_alias(base, new_name, old_name) {
|
|
550
|
+
define_method(base, new_name, base.$m_tbl[old_name]);
|
|
551
|
+
return Qnil;
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
Implementation for Class#allocate
|
|
556
|
+
*/
|
|
557
|
+
function obj_alloc(klass) {
|
|
558
|
+
var result = new RObject(klass, T_OBJECT);
|
|
559
|
+
return result;
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
Raise the exception class with the given string message.
|
|
564
|
+
*/
|
|
565
|
+
function raise(exc, str) {
|
|
566
|
+
if (str === undefined) {
|
|
567
|
+
str = exc;
|
|
568
|
+
exc = eException;
|
|
569
|
+
}
|
|
570
|
+
var exception = exc.$m.allocate(exc);
|
|
571
|
+
exception.message = str;
|
|
572
|
+
vm_raise(exception);
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
Raise an exception instance (DO NOT pass strings to this)
|
|
577
|
+
*/
|
|
578
|
+
function vm_raise(exc) {
|
|
579
|
+
throw exc;
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
Vm.raise = vm_raise;
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
Throw an argument error when the wrong number of arguments were given to a
|
|
586
|
+
method.
|
|
587
|
+
|
|
588
|
+
@param {Number} given The number of arguments actually given
|
|
589
|
+
@param {Number} expected The number of arguments we expected to have
|
|
590
|
+
*/
|
|
591
|
+
function arg_error(given, expected) {
|
|
592
|
+
raise(eArgError,
|
|
593
|
+
"wrong number of arguments(" + given + " for " + expected + ")");
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
Call a super method.
|
|
598
|
+
|
|
599
|
+
callee is the function that actually called super(). We use this to find
|
|
600
|
+
the right place in the tree to find the method that actually called super.
|
|
601
|
+
This is actually done in super_find.
|
|
602
|
+
*/
|
|
603
|
+
Vm.S = function(callee, self, args) {
|
|
604
|
+
var mid = callee.$rbName;
|
|
605
|
+
var func = super_find(self.$klass, callee, callee.$rbName);
|
|
606
|
+
|
|
607
|
+
if (!func) {
|
|
608
|
+
raise(eNoMethodError, "super: no superclass method for " + mid);
|
|
609
|
+
raise(eNoMethodError, "super: no super class method `" + mid + "`" +
|
|
610
|
+
" for " + self.$m.inspect(self));
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
var args_to_send = [self, mid].concat(args);
|
|
614
|
+
return func.apply(null, args_to_send);
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
Actually find super impl to call. Returns null if cannot find it.
|
|
619
|
+
*/
|
|
620
|
+
function super_find(klass, callee, mid) {
|
|
621
|
+
var cur_method;
|
|
622
|
+
|
|
623
|
+
while (klass) {
|
|
624
|
+
if (klass.$method_table[mid]) {
|
|
625
|
+
if (klass.$method_table[mid] == callee) {
|
|
626
|
+
break;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
klass = klass.$super;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (!klass) { return null; }
|
|
633
|
+
|
|
634
|
+
klass = klass.$super;
|
|
635
|
+
|
|
636
|
+
while (klass) {
|
|
637
|
+
if (klass.$method_table[mid]) {
|
|
638
|
+
return klass.$method_table[mid];
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
klass = klass.$super;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
return null;
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
VM method to get a contant from the given base.
|
|
649
|
+
|
|
650
|
+
@global
|
|
651
|
+
*/
|
|
652
|
+
rb_vm_cg = function(base, id) {
|
|
653
|
+
if (base.$flags & T_OBJECT) {
|
|
654
|
+
base = class_real(base.$klass);
|
|
655
|
+
}
|
|
656
|
+
return const_get(base, id);
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
VM method to set a contant in base.
|
|
661
|
+
|
|
662
|
+
@global
|
|
663
|
+
*/
|
|
664
|
+
rb_vm_cs = function(base, id, val) {
|
|
665
|
+
if (base.$flags & T_OBJECT) {
|
|
666
|
+
base = class_real(base.$klass);
|
|
667
|
+
}
|
|
668
|
+
return const_set(base, id, val);
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
Get global by id
|
|
673
|
+
*/
|
|
674
|
+
Vm.gg = function(id) {
|
|
675
|
+
return gvar_get(id);
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
Set global by id
|
|
680
|
+
*/
|
|
681
|
+
Vm.gs = function(id, value) {
|
|
682
|
+
return gvar_set(id, value);
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
Getter method for getting the load path for opal.
|
|
687
|
+
|
|
688
|
+
@param {String} id The globals id being retrieved.
|
|
689
|
+
@return {Array} Load paths
|
|
690
|
+
*/
|
|
691
|
+
function load_path_getter(id) {
|
|
692
|
+
return opal.loader.paths;
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
Getter method to get all loaded features.
|
|
697
|
+
|
|
698
|
+
@param {String} id Feature global id
|
|
699
|
+
@return {Array} Loaded features
|
|
700
|
+
*/
|
|
701
|
+
function loaded_feature_getter(id) {
|
|
702
|
+
return loaded_features;
|
|
703
|
+
};
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
Main init method. This is called once this file has fully loaded. It setups
|
|
707
|
+
all the core objects and classes and required runtime features.
|
|
708
|
+
*/
|
|
709
|
+
function init() {
|
|
710
|
+
|
|
711
|
+
var metaclass;
|
|
712
|
+
|
|
713
|
+
Vm.BasicObject = cBasicObject = boot_defrootclass('BasicObject');
|
|
714
|
+
Vm.Object = cObject = boot_defclass('Object', cBasicObject);
|
|
715
|
+
Vm.Module = cModule = boot_defclass('Module', cObject);
|
|
716
|
+
Vm.Class = cClass = boot_defclass('Class', cModule);
|
|
717
|
+
|
|
718
|
+
const_set(cObject, 'BasicObject', cBasicObject);
|
|
719
|
+
|
|
720
|
+
metaclass = make_metaclass(cBasicObject, cClass);
|
|
721
|
+
metaclass = make_metaclass(cObject, metaclass);
|
|
722
|
+
metaclass = make_metaclass(cModule, metaclass);
|
|
723
|
+
metaclass = make_metaclass(cClass, metaclass);
|
|
724
|
+
|
|
725
|
+
boot_defmetametaclass(cModule, metaclass);
|
|
726
|
+
boot_defmetametaclass(cObject, metaclass);
|
|
727
|
+
boot_defmetametaclass(cBasicObject, metaclass);
|
|
728
|
+
|
|
729
|
+
define_method(cBasicObject, "!", obj_not);
|
|
730
|
+
define_method(cBasicObject, "!=", obj_not_equal);
|
|
731
|
+
|
|
732
|
+
mKernel = define_module('Kernel');
|
|
733
|
+
|
|
734
|
+
include_module(cObject, mKernel);
|
|
735
|
+
|
|
736
|
+
define_method(cClass, "allocate", obj_alloc);
|
|
737
|
+
define_method(cClass, "new", class_new_instance);
|
|
738
|
+
define_method(cClass, "initialize", class_initialize);
|
|
739
|
+
define_singleton_method(cClass, "new", class_s_new);
|
|
740
|
+
|
|
741
|
+
define_method(mKernel, "puts", obj_puts);
|
|
742
|
+
|
|
743
|
+
Qself = obj_alloc(cObject);
|
|
744
|
+
Vm.top = Qself;
|
|
745
|
+
|
|
746
|
+
cNilClass = define_class('NilClass', cObject);
|
|
747
|
+
Vm.Qnil = Qnil = obj_alloc(cNilClass);
|
|
748
|
+
Qnil.$r = false;
|
|
749
|
+
|
|
750
|
+
cTrueClass = define_class('TrueClass', cObject);
|
|
751
|
+
Vm.Qtrue = Qtrue = obj_alloc(cTrueClass);
|
|
752
|
+
|
|
753
|
+
cFalseClass = define_class('FalseClass', cObject);
|
|
754
|
+
Vm.Qfalse = Qfalse = obj_alloc(cFalseClass);
|
|
755
|
+
Qfalse.$r = false;
|
|
756
|
+
|
|
757
|
+
cArray = bridge_class(Array.prototype,
|
|
758
|
+
T_OBJECT | T_ARRAY, 'Array', cObject);
|
|
759
|
+
|
|
760
|
+
Array.prototype.$hash = function() {
|
|
761
|
+
return (this.$id || (this.$id = yield_hash()));
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
cNumeric = bridge_class(Number.prototype,
|
|
765
|
+
T_OBJECT | T_NUMBER, 'Numeric', cObject);
|
|
766
|
+
|
|
767
|
+
cHash = bridge_class(RHash.prototype,
|
|
768
|
+
T_OBJECT | T_HASH, 'Hash', cObject);
|
|
769
|
+
|
|
770
|
+
RHash.prototype.$hash = function() {
|
|
771
|
+
return (this.$id || (this.$id = yield_hash()));
|
|
772
|
+
};
|
|
773
|
+
|
|
774
|
+
define_singleton_method(cHash, '[]', hash_s_create);
|
|
775
|
+
|
|
776
|
+
cRegexp = bridge_class(RegExp.prototype, T_OBJECT,
|
|
777
|
+
'Regexp', cObject);
|
|
778
|
+
|
|
779
|
+
define_hooked_variable('$:', load_path_getter, gvar_readonly_setter);
|
|
780
|
+
define_hooked_variable('$LOAD_PATH', load_path_getter, gvar_readonly_setter);
|
|
781
|
+
|
|
782
|
+
const_set(cObject, 'ARGV', []);
|
|
783
|
+
|
|
784
|
+
eException = bridge_class(Error.prototype, T_OBJECT, 'Exception', cObject);
|
|
785
|
+
|
|
786
|
+
eStandardError = define_class("StandardError", eException);
|
|
787
|
+
eRuntimeError = define_class("RuntimeError", eException);
|
|
788
|
+
eLocalJumpError = define_class("LocalJumpError", eStandardError);
|
|
789
|
+
eTypeError = define_class("TypeError", eStandardError);
|
|
790
|
+
eNameError = define_class("NameError", eStandardError);
|
|
791
|
+
eNoMethodError = define_class('NoMethodError', eNameError);
|
|
792
|
+
eArgError = define_class('ArgumentError', eStandardError);
|
|
793
|
+
eScriptError = define_class('ScriptError', eException);
|
|
794
|
+
eLoadError = define_class('LoadError', eScriptError);
|
|
795
|
+
|
|
796
|
+
eIndexError = define_class("IndexError", eStandardError);
|
|
797
|
+
eKeyError = define_class("KeyError", eIndexError);
|
|
798
|
+
eRangeError = define_class("RangeError", eStandardError);
|
|
799
|
+
|
|
800
|
+
rb_vm_break_instance = new Error('unexpected break');
|
|
801
|
+
rb_vm_break_instance.$klass = eLocalJumpError;
|
|
802
|
+
rb_vm_break_instance.$keyword = 2;
|
|
803
|
+
|
|
804
|
+
rb_vm_return_instance = new Error('unexpected return');
|
|
805
|
+
rb_vm_return_instance.$klass = eLocalJumpError;
|
|
806
|
+
rb_vm_return_instance.$keyword = 1;
|
|
807
|
+
|
|
808
|
+
rb_vm_next_instance = new Error('unexpected next');
|
|
809
|
+
rb_vm_next_instance.$klass = eLocalJumpError;
|
|
810
|
+
rb_vm_next_instance.$keyword = 3;
|
|
811
|
+
|
|
812
|
+
cString = bridge_class(String.prototype,
|
|
813
|
+
T_OBJECT | T_STRING, 'String', cObject);
|
|
814
|
+
|
|
815
|
+
cSymbol = define_class('Symbol', cObject);
|
|
816
|
+
|
|
817
|
+
cProc = bridge_class(Function.prototype,
|
|
818
|
+
T_OBJECT | T_PROC, 'Proc', cObject);
|
|
819
|
+
|
|
820
|
+
Function.prototype.$hash = function() {
|
|
821
|
+
return (this.$id || (this.$id = yield_hash()));
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
cRange = bridge_class(RRange.prototype, T_OBJECT | T_RANGE,
|
|
825
|
+
'Range', cObject);
|
|
826
|
+
|
|
827
|
+
RRange.prototype.$hash = function() {
|
|
828
|
+
return (this.$id || (this.$id = yield_hash()));
|
|
829
|
+
};
|
|
830
|
+
|
|
831
|
+
const_set(cObject, 'RUBY_PLATFORM', 'opal');
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
Define a top level module with the given id
|
|
836
|
+
*/
|
|
837
|
+
function define_module(id) {
|
|
838
|
+
return define_module_under(cObject, id);
|
|
839
|
+
};
|
|
840
|
+
|
|
841
|
+
function define_module_under(base, id) {
|
|
842
|
+
var module;
|
|
843
|
+
|
|
844
|
+
if (const_defined(base, id)) {
|
|
845
|
+
module = const_get(base, id);
|
|
846
|
+
if (module.$flags & T_MODULE) {
|
|
847
|
+
return module;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
throw id + " is not a module.";
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
module = define_module_id(id);
|
|
854
|
+
const_set(base, id, module);
|
|
855
|
+
module.$parent = base;
|
|
856
|
+
return module;
|
|
857
|
+
};
|
|
858
|
+
|
|
859
|
+
function define_module_id(id) {
|
|
860
|
+
var module = define_class_id(id, cModule);
|
|
861
|
+
module.$flags = T_MODULE;
|
|
862
|
+
name_class(module, id);
|
|
863
|
+
return module;
|
|
864
|
+
};
|
|
865
|
+
|
|
866
|
+
function mod_create() {
|
|
867
|
+
return class_boot(cModule);
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
function include_module(klass, module) {
|
|
871
|
+
|
|
872
|
+
if (!klass.$included_modules) {
|
|
873
|
+
klass.$included_modules = [];
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
if (klass.$included_modules.indexOf(module) != -1) {
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
klass.$included_modules.push(module);
|
|
880
|
+
|
|
881
|
+
if (!module.$included_in) {
|
|
882
|
+
module.$included_in = [];
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
module.$included_in.push(klass);
|
|
886
|
+
|
|
887
|
+
for (var method in module.$method_table) {
|
|
888
|
+
if (module.$method_table.hasOwnProperty(method)) {
|
|
889
|
+
define_method(klass, method, module.$method_table[method]);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
};
|
|
893
|
+
|
|
894
|
+
Vm.include_module = include_module;
|
|
895
|
+
|
|
896
|
+
function extend_module(klass, module) {
|
|
897
|
+
if (!klass.$extended_modules) {
|
|
898
|
+
klass.$extended_modules = [];
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
if (klass.$extended_modules.indexOf(module) != -1) {
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
klass.$extended_modules.push(module);
|
|
905
|
+
|
|
906
|
+
if (!module.$extended_in) {
|
|
907
|
+
module.$extended_in = [];
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
module.$extended_in.push(klass);
|
|
911
|
+
|
|
912
|
+
var meta = klass.$klass;
|
|
913
|
+
|
|
914
|
+
for (var method in module.$method_table) {
|
|
915
|
+
if (module.$method_table.hasOwnProperty(method)) {
|
|
916
|
+
define_method(meta, method, module.$method_table[method]);
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
};
|
|
920
|
+
|
|
921
|
+
Vm.extend_module = extend_module;
|
|
922
|
+
|
|
923
|
+
/**
|
|
924
|
+
Boot a base class (only used for very core object classes)
|
|
925
|
+
*/
|
|
926
|
+
function boot_defclass(id, super_klass) {
|
|
927
|
+
var result = class_boot(super_klass);
|
|
928
|
+
name_class(result, id);
|
|
929
|
+
const_set((cObject || result), id, result);
|
|
930
|
+
return result;
|
|
931
|
+
};
|
|
932
|
+
|
|
933
|
+
/**
|
|
934
|
+
Like boot_defclass, but for root object only (i.e. basicobject)
|
|
935
|
+
*/
|
|
936
|
+
function boot_defrootclass(id) {
|
|
937
|
+
var result = new RClass(null, null);
|
|
938
|
+
result.$flags = T_CLASS;
|
|
939
|
+
name_class(result, id);
|
|
940
|
+
const_set((cObject || result), id, result);
|
|
941
|
+
return result;
|
|
942
|
+
};
|
|
943
|
+
|
|
944
|
+
function class_boot(super_class) {
|
|
945
|
+
if (super_class) {
|
|
946
|
+
var ctor = function() {};
|
|
947
|
+
ctor.prototype = super_class.constructor.prototype;
|
|
948
|
+
|
|
949
|
+
var result = function() {
|
|
950
|
+
RClass.call(this, null, super_class);
|
|
951
|
+
return this;
|
|
952
|
+
};
|
|
953
|
+
result.prototype = new ctor();
|
|
954
|
+
|
|
955
|
+
var klass = new result();
|
|
956
|
+
klass.$klass = cClass;
|
|
957
|
+
return klass;
|
|
958
|
+
}
|
|
959
|
+
else {
|
|
960
|
+
var result = new RClass(null, null);
|
|
961
|
+
return result;
|
|
962
|
+
}
|
|
963
|
+
};
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
@global
|
|
967
|
+
*/
|
|
968
|
+
function class_real(klass) {
|
|
969
|
+
while (klass.$flags & FL_SINGLETON) { klass = klass.$super; }
|
|
970
|
+
return klass;
|
|
971
|
+
};
|
|
972
|
+
|
|
973
|
+
Vm.class_real = class_real;
|
|
974
|
+
|
|
975
|
+
/**
|
|
976
|
+
Name the class with the given id.
|
|
977
|
+
*/
|
|
978
|
+
function name_class(klass, id) {
|
|
979
|
+
klass.__classid__ = id;
|
|
980
|
+
};
|
|
981
|
+
|
|
982
|
+
/**
|
|
983
|
+
Make metaclass for the given class
|
|
984
|
+
*/
|
|
985
|
+
function make_metaclass(klass, super_class) {
|
|
986
|
+
if ((klass.$flags & T_CLASS) && (klass.$flags & FL_SINGLETON)) {
|
|
987
|
+
return make_metametaclass(klass);
|
|
988
|
+
}
|
|
989
|
+
else {
|
|
990
|
+
var meta = class_boot(super_class);
|
|
991
|
+
meta.$flags |= FL_SINGLETON;
|
|
992
|
+
klass.$klass = meta;
|
|
993
|
+
klass.$m = meta.$m_tbl;
|
|
994
|
+
meta.$c = klass.$c;
|
|
995
|
+
singleton_class_attached(meta, klass);
|
|
996
|
+
|
|
997
|
+
return meta;
|
|
998
|
+
}
|
|
999
|
+
};
|
|
1000
|
+
|
|
1001
|
+
function singleton_class_attached(klass, obj) {
|
|
1002
|
+
if (klass.$flags & FL_SINGLETON) {
|
|
1003
|
+
ivar_set(klass, '__attached__', obj);
|
|
1004
|
+
}
|
|
1005
|
+
};
|
|
1006
|
+
|
|
1007
|
+
function make_metametaclass(metaclass) {
|
|
1008
|
+
var metametaclass, super_of_metaclass;
|
|
1009
|
+
|
|
1010
|
+
if (metaclass.$klass == metaclass) {
|
|
1011
|
+
metametaclass = class_boot(null);
|
|
1012
|
+
metametaclass.$klass = metametaclass;
|
|
1013
|
+
}
|
|
1014
|
+
else {
|
|
1015
|
+
metametaclass = class_boot(null);
|
|
1016
|
+
metametaclass.$klass = metaclass.$klass.$klass == metaclass.$klass
|
|
1017
|
+
? make_metametaclass(metaclass.$klass)
|
|
1018
|
+
: metaclass.$klass.$klass;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
metametaclass.$flags |= FL_SINGLETON;
|
|
1022
|
+
|
|
1023
|
+
singleton_class_attached(metametaclass, metaclass);
|
|
1024
|
+
metaclass.$klass = metametaclass;
|
|
1025
|
+
metaclass.$m = metametaclass.$m_tbl;
|
|
1026
|
+
super_of_metaclass = metaclass.$super;
|
|
1027
|
+
|
|
1028
|
+
metametaclass.$super = ivar_get(super_of_metaclass.$klass, '__attached__')
|
|
1029
|
+
== super_of_metaclass
|
|
1030
|
+
? super_of_metaclass.$klass
|
|
1031
|
+
: make_metametaclass(super_of_metaclass);
|
|
1032
|
+
|
|
1033
|
+
return metametaclass;
|
|
1034
|
+
};
|
|
1035
|
+
|
|
1036
|
+
function boot_defmetametaclass(klass, metametaclass) {
|
|
1037
|
+
klass.$klass.$klass = metametaclass;
|
|
1038
|
+
};
|
|
1039
|
+
|
|
1040
|
+
/**
|
|
1041
|
+
Define toll free bridged class
|
|
1042
|
+
*/
|
|
1043
|
+
function bridge_class(prototype, flags, id, super_class) {
|
|
1044
|
+
var klass = define_class(id, super_class);
|
|
1045
|
+
|
|
1046
|
+
prototype.$klass = klass;
|
|
1047
|
+
prototype.$m = klass.$m_tbl;
|
|
1048
|
+
prototype.$flags = flags;
|
|
1049
|
+
prototype.$r = true;
|
|
1050
|
+
|
|
1051
|
+
prototype.$hash = function() {
|
|
1052
|
+
return flags + '_' + this;
|
|
1053
|
+
};
|
|
1054
|
+
|
|
1055
|
+
return klass;
|
|
1056
|
+
};
|
|
1057
|
+
|
|
1058
|
+
/**
|
|
1059
|
+
Define a new class (normal way), with the given id and superclass. Will be
|
|
1060
|
+
top level.
|
|
1061
|
+
*/
|
|
1062
|
+
function define_class(id, super_klass) {
|
|
1063
|
+
return define_class_under(cObject, id, super_klass);
|
|
1064
|
+
};
|
|
1065
|
+
|
|
1066
|
+
function define_class_under(base, id, super_klass) {
|
|
1067
|
+
var klass;
|
|
1068
|
+
|
|
1069
|
+
if (const_defined(base, id)) {
|
|
1070
|
+
return const_get(base, id);
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
klass = define_class_id(id, super_klass);
|
|
1074
|
+
|
|
1075
|
+
name_class(klass, id);
|
|
1076
|
+
const_set(base, id, klass);
|
|
1077
|
+
klass.$parent = base;
|
|
1078
|
+
return klass;
|
|
1079
|
+
};
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
Actually create class
|
|
1083
|
+
*/
|
|
1084
|
+
function define_class_id(id, super_klass) {
|
|
1085
|
+
var klass;
|
|
1086
|
+
|
|
1087
|
+
if (!super_klass) {
|
|
1088
|
+
super_klass = cObject;
|
|
1089
|
+
}
|
|
1090
|
+
klass = class_create(super_klass);
|
|
1091
|
+
name_class(klass, id);
|
|
1092
|
+
make_metaclass(klass, super_klass.$klass);
|
|
1093
|
+
return klass;
|
|
1094
|
+
};
|
|
1095
|
+
|
|
1096
|
+
function class_create(super_klass) {
|
|
1097
|
+
return class_boot(super_klass);
|
|
1098
|
+
};
|
|
1099
|
+
|
|
1100
|
+
/**
|
|
1101
|
+
Get singleton class of obj
|
|
1102
|
+
*/
|
|
1103
|
+
function singleton_class(obj) {
|
|
1104
|
+
var obj;
|
|
1105
|
+
|
|
1106
|
+
if ((obj.$klass.$flags & FL_SINGLETON)&& ivar_get(obj.$klass, '__attached__') == obj) {
|
|
1107
|
+
klass = obj.$klass;
|
|
1108
|
+
}
|
|
1109
|
+
else {
|
|
1110
|
+
var class_id = obj.$klass.__classid__;
|
|
1111
|
+
klass = make_metaclass(obj, obj.$klass);
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
return klass;
|
|
1115
|
+
};
|
|
1116
|
+
|
|
1117
|
+
function RHash(args) {
|
|
1118
|
+
var k, v;
|
|
1119
|
+
this.$keys = [];
|
|
1120
|
+
this.$assocs = {};
|
|
1121
|
+
this.$default = Qnil;
|
|
1122
|
+
|
|
1123
|
+
for (var i = 0; i < args.length; i++) {
|
|
1124
|
+
k = args[i];
|
|
1125
|
+
v = args[i+1];
|
|
1126
|
+
i++;
|
|
1127
|
+
this.$keys.push(k);
|
|
1128
|
+
this.$assocs[k.$hash()] = v;
|
|
1129
|
+
}
|
|
1130
|
+
return this;
|
|
1131
|
+
};
|
|
1132
|
+
|
|
1133
|
+
/**
|
|
1134
|
+
Symbol table. All symbols are stored here.
|
|
1135
|
+
*/
|
|
1136
|
+
var symbol_table = { };
|
|
1137
|
+
|
|
1138
|
+
/**
|
|
1139
|
+
Range ruby object
|
|
1140
|
+
*/
|
|
1141
|
+
function RRange(beg, end, exclude_end) {
|
|
1142
|
+
this.$beg = beg;
|
|
1143
|
+
this.$end = end;
|
|
1144
|
+
this.$exc = exclude_end;
|
|
1145
|
+
return this;
|
|
1146
|
+
};
|
|
1147
|
+
|
|
1148
|
+
/**
|
|
1149
|
+
Creates a new hash populated with the given objects. Equivalent to the
|
|
1150
|
+
literal `{ key => value, ... }`.
|
|
1151
|
+
|
|
1152
|
+
@example
|
|
1153
|
+
Hash["a", 100, "b", 200]
|
|
1154
|
+
# => {"a" =>100, "b"=>200}
|
|
1155
|
+
|
|
1156
|
+
@return [Hash]
|
|
1157
|
+
*/
|
|
1158
|
+
function hash_s_create(obj, mid) {
|
|
1159
|
+
return opalhash.apply(null, Array.prototype.slice.call(arguments, 2));
|
|
1160
|
+
};
|
|
1161
|
+
|
|
1162
|
+
function class_s_new(cls, sup) {
|
|
1163
|
+
var klass = define_class_id("AnonClass", sup || cObject);
|
|
1164
|
+
return klass;
|
|
1165
|
+
};
|
|
1166
|
+
|
|
1167
|
+
function class_new_instance(cls) {
|
|
1168
|
+
var obj = cls.$m.allocate(cls);
|
|
1169
|
+
var args = Array.prototype.slice.call(arguments, 1);
|
|
1170
|
+
args.unshift(obj);
|
|
1171
|
+
|
|
1172
|
+
if (Vm.P.f == arguments.callee) {
|
|
1173
|
+
VM.P.f = obj.$m.initialize;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
obj.$m.initialize.apply(obj, args);
|
|
1177
|
+
return obj;
|
|
1178
|
+
};
|
|
1179
|
+
|
|
1180
|
+
function class_initialize(cla, mid, sup) {
|
|
1181
|
+
var klass = define_class_id('', sup || cObject);
|
|
1182
|
+
return klass;
|
|
1183
|
+
};
|
|
1184
|
+
|
|
1185
|
+
/**
|
|
1186
|
+
Prints each argument in turn to the browser console. Currently there is no
|
|
1187
|
+
use of `$stdout`, so it is hardcoded into this method to write to the
|
|
1188
|
+
console directly.
|
|
1189
|
+
|
|
1190
|
+
@param {Object} args objects to print using `inspect`
|
|
1191
|
+
@return {nil}
|
|
1192
|
+
*/
|
|
1193
|
+
function obj_puts(obj) {
|
|
1194
|
+
var args = Array.prototype.slice.call(arguments, 1);
|
|
1195
|
+
|
|
1196
|
+
for (var i = 0; i < args.length; i++) {
|
|
1197
|
+
console.log((args[i].$m.to_s(args[i])).toString());
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
return Qnil;
|
|
1201
|
+
};
|
|
1202
|
+
|
|
1203
|
+
/**
|
|
1204
|
+
@example
|
|
1205
|
+
!obj # => true or false
|
|
1206
|
+
*/
|
|
1207
|
+
function obj_not(obj, mid) {
|
|
1208
|
+
return obj.$r ? Qfalse : Qtrue;
|
|
1209
|
+
};
|
|
1210
|
+
|
|
1211
|
+
/**
|
|
1212
|
+
@example
|
|
1213
|
+
obj != obj2 # => true or false
|
|
1214
|
+
*/
|
|
1215
|
+
function obj_not_equal(obj1, mid, obj2) {
|
|
1216
|
+
var res = obj1.$m['=='](obj1, obj2);
|
|
1217
|
+
return res.$r ? Qfalse : Qtrue;
|
|
1218
|
+
};
|
|
1219
|
+
|
|
1220
|
+
// ..........................................................
|
|
1221
|
+
// FILESYSTEM
|
|
1222
|
+
//
|
|
1223
|
+
|
|
1224
|
+
// added to main opal namespace, and Fs for minimizing here.
|
|
1225
|
+
var Fs = Op.fs = {};
|
|
1226
|
+
|
|
1227
|
+
/**
|
|
1228
|
+
Regular expression used for splitting filenames into their dirname,
|
|
1229
|
+
basename and extension. This is unix style only, as filenames inside
|
|
1230
|
+
opal in the browser will only ever have this style of filename. The gem
|
|
1231
|
+
fs support will depend on the platform being run.
|
|
1232
|
+
**/
|
|
1233
|
+
var PATH_RE = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;
|
|
1234
|
+
|
|
1235
|
+
/**
|
|
1236
|
+
Holds the current working directory for the application. This is '/' by
|
|
1237
|
+
default, but is usually set to the base directory of the main gem.
|
|
1238
|
+
|
|
1239
|
+
@type {String}
|
|
1240
|
+
*/
|
|
1241
|
+
Fs.cwd = '/';
|
|
1242
|
+
|
|
1243
|
+
/**
|
|
1244
|
+
Join the given args using the default seperator. The path returned is not
|
|
1245
|
+
expanded.
|
|
1246
|
+
|
|
1247
|
+
@param {arguments<String<} args The arguments to join
|
|
1248
|
+
@return {String}
|
|
1249
|
+
*/
|
|
1250
|
+
var file_join = Fs.join = function() {
|
|
1251
|
+
var parts = [].slice.call(arguments, 0);
|
|
1252
|
+
return parts.join('/');
|
|
1253
|
+
};
|
|
1254
|
+
|
|
1255
|
+
/**
|
|
1256
|
+
Normalize the path by removing '..' and '.' parts, remove '//' etc to
|
|
1257
|
+
return a nice normalized path.
|
|
1258
|
+
|
|
1259
|
+
@param {String} path The path needing normalization
|
|
1260
|
+
@param {String} base Optional base to normalize to
|
|
1261
|
+
@return {String} Normalized path
|
|
1262
|
+
*/
|
|
1263
|
+
var file_expand_path = Fs.expand_path = function(path, base) {
|
|
1264
|
+
path = file_join(base || Fs.cwd, path);
|
|
1265
|
+
|
|
1266
|
+
var parts = path.split('/'), result = [], part;
|
|
1267
|
+
|
|
1268
|
+
// initial /
|
|
1269
|
+
if (parts[0] === '') result.push('');
|
|
1270
|
+
|
|
1271
|
+
for (var i = 0, ii = parts.length; i < ii; i++) {
|
|
1272
|
+
part = parts[i];
|
|
1273
|
+
|
|
1274
|
+
if (part == '..') {
|
|
1275
|
+
result.pop();
|
|
1276
|
+
}
|
|
1277
|
+
else if (part == '.' || part == '') {
|
|
1278
|
+
|
|
1279
|
+
}
|
|
1280
|
+
else {
|
|
1281
|
+
result.push(part);
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
return result.join('/');
|
|
1286
|
+
};
|
|
1287
|
+
|
|
1288
|
+
/**
|
|
1289
|
+
Returns all of the components of the given `file_name` except for the last
|
|
1290
|
+
one.
|
|
1291
|
+
|
|
1292
|
+
@param {String} file_name
|
|
1293
|
+
@return {String}
|
|
1294
|
+
*/
|
|
1295
|
+
var file_dirname = Fs.dirname = function(file_name) {
|
|
1296
|
+
var dirname = PATH_RE.exec(file_name)[1];
|
|
1297
|
+
|
|
1298
|
+
if (!dirname) return '.';
|
|
1299
|
+
else if (dirname === '/') return dirname;
|
|
1300
|
+
else return dirname.substring(0, dirname.length - 1);
|
|
1301
|
+
};
|
|
1302
|
+
|
|
1303
|
+
/**
|
|
1304
|
+
Returns the file extension of the given `file_name`.
|
|
1305
|
+
|
|
1306
|
+
@param {String} file_name
|
|
1307
|
+
@return {String}
|
|
1308
|
+
*/
|
|
1309
|
+
Fs.extname = function(file_name) {
|
|
1310
|
+
var extname = PATH_RE.exec(file_name)[3];
|
|
1311
|
+
|
|
1312
|
+
if (!extname || extname === '.') return '';
|
|
1313
|
+
else return extname;
|
|
1314
|
+
};
|
|
1315
|
+
|
|
1316
|
+
|
|
1317
|
+
// ..........................................................
|
|
1318
|
+
// LOADER
|
|
1319
|
+
//
|
|
1320
|
+
|
|
1321
|
+
/**
|
|
1322
|
+
Require a module.
|
|
1323
|
+
|
|
1324
|
+
@param {String} id The module id
|
|
1325
|
+
@return {Object} returns the exports
|
|
1326
|
+
*/
|
|
1327
|
+
Op.require = function(id, parent) {
|
|
1328
|
+
var resolved = Op.loader.resolve_module(id, null);
|
|
1329
|
+
var cached = Op.cache[resolved];
|
|
1330
|
+
|
|
1331
|
+
if (cached) {
|
|
1332
|
+
return true;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
Op.cache[resolved] = true;
|
|
1336
|
+
// try/catch?
|
|
1337
|
+
load_file(Op.loader, resolved);
|
|
1338
|
+
|
|
1339
|
+
return true;
|
|
1340
|
+
};
|
|
1341
|
+
|
|
1342
|
+
// Virtual machine must also be able to require..
|
|
1343
|
+
Vm.require = Op.require;
|
|
1344
|
+
|
|
1345
|
+
/**
|
|
1346
|
+
Register a package with the given package info.
|
|
1347
|
+
|
|
1348
|
+
This will probably (definately??) always be done only in the browser.
|
|
1349
|
+
|
|
1350
|
+
@param {String} name The package name
|
|
1351
|
+
@param {Object} info The package info
|
|
1352
|
+
*/
|
|
1353
|
+
Op.register = function(name, info) {
|
|
1354
|
+
|
|
1355
|
+
// make sure we get a string name
|
|
1356
|
+
if (typeof name !== 'string') {
|
|
1357
|
+
throw new Error("Cannot register a package without a proper name");
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
// registering a single module/file
|
|
1361
|
+
if (typeof info === 'string' || typeof info === 'function') {
|
|
1362
|
+
register_module(name, info);
|
|
1363
|
+
}
|
|
1364
|
+
// make sure info is a proper package
|
|
1365
|
+
else if (typeof info === 'object') {
|
|
1366
|
+
register_package(name, info);
|
|
1367
|
+
}
|
|
1368
|
+
// else, we have an error.. we can only register packages or modules
|
|
1369
|
+
else {
|
|
1370
|
+
throw new Error("Invalid package.json data for '" + name + "'");
|
|
1371
|
+
}
|
|
1372
|
+
};
|
|
1373
|
+
|
|
1374
|
+
/**
|
|
1375
|
+
Private method to actually register the package. This is private to
|
|
1376
|
+
avoid external interferance. This will be called from {opal#register}.
|
|
1377
|
+
|
|
1378
|
+
@param {String} name The package name
|
|
1379
|
+
@param {Object} info The package information
|
|
1380
|
+
*/
|
|
1381
|
+
var register_package = function(name, info) {
|
|
1382
|
+
var factories = Op.loader.factories,
|
|
1383
|
+
paths = Op.loader.paths;
|
|
1384
|
+
|
|
1385
|
+
// register all files
|
|
1386
|
+
var files = info.files || {};
|
|
1387
|
+
|
|
1388
|
+
// root dir for package is /package_name
|
|
1389
|
+
var root_dir = '/' + name;
|
|
1390
|
+
|
|
1391
|
+
// assume './lib' dir for lib files (for now.. should be dynamic)
|
|
1392
|
+
var lib_dir = './lib';
|
|
1393
|
+
|
|
1394
|
+
// add lib dir to paths
|
|
1395
|
+
paths.unshift(file_expand_path(file_join(root_dir, lib_dir)));
|
|
1396
|
+
|
|
1397
|
+
for (var file in files) {
|
|
1398
|
+
if (files.hasOwnProperty(file)) {
|
|
1399
|
+
// full path to file; we use the root dir
|
|
1400
|
+
var file_path = file_expand_path(file_join(root_dir, file));
|
|
1401
|
+
|
|
1402
|
+
factories[file_path] = files[file];
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
////////////////////////////////////////
|
|
1407
|
+
// Autobooting. Basically, autoload opal.
|
|
1408
|
+
//
|
|
1409
|
+
if (name === 'opal') {
|
|
1410
|
+
Op.require(name);
|
|
1411
|
+
}
|
|
1412
|
+
};
|
|
1413
|
+
|
|
1414
|
+
/**
|
|
1415
|
+
Private method to register a single module. These modules are added to the
|
|
1416
|
+
very top level dir: /module_name.js
|
|
1417
|
+
*/
|
|
1418
|
+
var register_module = function(name, factory) {
|
|
1419
|
+
// name gets preceeded with a '/' for root files
|
|
1420
|
+
var factory_name = '/' + name;
|
|
1421
|
+
|
|
1422
|
+
Op.loader.factories[factory_name] = factory;
|
|
1423
|
+
};
|
|
1424
|
+
|
|
1425
|
+
|
|
1426
|
+
// valid extensions for loading
|
|
1427
|
+
var load_extensions = {};
|
|
1428
|
+
|
|
1429
|
+
load_extensions['.js'] = function(loader, filename) {
|
|
1430
|
+
var source = loader.module_contents(filename);
|
|
1431
|
+
return execute_file(loader, source, filename);
|
|
1432
|
+
};
|
|
1433
|
+
|
|
1434
|
+
load_extensions['.rb'] = function(loader, filename) {
|
|
1435
|
+
var source = loader.ruby_module_contents(filename);
|
|
1436
|
+
return execute_file(loader, source, filename);
|
|
1437
|
+
};
|
|
1438
|
+
|
|
1439
|
+
/**
|
|
1440
|
+
The loader is the core machinery used for loading and executing modules
|
|
1441
|
+
within opal. An instance of opal will have a .loader property, which
|
|
1442
|
+
is an instance of this Loader class. A Loader is responsible for finding,
|
|
1443
|
+
opening and reading the contents of modules on disk. Within the browser,
|
|
1444
|
+
which is the default environment, a loader will use XHR requests or cached
|
|
1445
|
+
modules from JSON to load the required modules.
|
|
1446
|
+
|
|
1447
|
+
Within the browser, the loader, currently, just looks at its opal
|
|
1448
|
+
instance for registered files and packages and uses them as needed.
|
|
1449
|
+
opal also has 'built in' packages from commonjs, like 'system' etc, so
|
|
1450
|
+
all loaders must check opal first for registered packages.
|
|
1451
|
+
|
|
1452
|
+
@param {opal} opal The opal instance for this loader
|
|
1453
|
+
*/
|
|
1454
|
+
var Loader = function(opal) {
|
|
1455
|
+
this.opal = opal;
|
|
1456
|
+
this.paths = [''];
|
|
1457
|
+
|
|
1458
|
+
this.factories = {};
|
|
1459
|
+
|
|
1460
|
+
|
|
1461
|
+
return this;
|
|
1462
|
+
};
|
|
1463
|
+
|
|
1464
|
+
// Loader prototype
|
|
1465
|
+
var Lp = Loader.prototype;
|
|
1466
|
+
|
|
1467
|
+
/**
|
|
1468
|
+
The paths property is an array of disk paths in which to search for
|
|
1469
|
+
required modules. In the browser this functionality isn't really used.
|
|
1470
|
+
|
|
1471
|
+
This array is created within the constructor method for uniqueness
|
|
1472
|
+
between instances for correct sandboxing.
|
|
1473
|
+
*/
|
|
1474
|
+
Lp.paths = null;
|
|
1475
|
+
|
|
1476
|
+
/**
|
|
1477
|
+
factories of registered packages, paths => function/string. This is
|
|
1478
|
+
generic, but in reality only the browser uses this, and it is treated
|
|
1479
|
+
as the mini filesystem. Not just factories can go here, anything can!
|
|
1480
|
+
Images, text, json, whatever.
|
|
1481
|
+
*/
|
|
1482
|
+
Lp.factories = {};
|
|
1483
|
+
|
|
1484
|
+
/**
|
|
1485
|
+
Valid factory format for use in require();
|
|
1486
|
+
*/
|
|
1487
|
+
Lp.valid_extensions = ['.js', '.rb'];
|
|
1488
|
+
|
|
1489
|
+
/**
|
|
1490
|
+
Resolves the path to the module, which can then be used to load. This
|
|
1491
|
+
method will throw an error if the module cannot be found. If this method
|
|
1492
|
+
returns a successful filename, then subsequent methods like load_module
|
|
1493
|
+
should be successful and should not throw errors.
|
|
1494
|
+
|
|
1495
|
+
@param {String} id The id to look for
|
|
1496
|
+
@param {Module} parent The module that has requested the id
|
|
1497
|
+
*/
|
|
1498
|
+
Lp.resolve_module = function(id, parent) {
|
|
1499
|
+
var resolved = this.find_module(id, this.paths);
|
|
1500
|
+
|
|
1501
|
+
if (!resolved) {
|
|
1502
|
+
throw new Error("Cannot find module '" + id + "'");
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
return resolved;
|
|
1506
|
+
};
|
|
1507
|
+
|
|
1508
|
+
Lp.find_module = function(id, paths) {
|
|
1509
|
+
var extensions = this.valid_extensions, factories = this.factories, candidate;
|
|
1510
|
+
|
|
1511
|
+
for (var i = 0, ii = paths.length; i < ii; i++) {
|
|
1512
|
+
for (var j = 0, jj = extensions.length; j < jj; j++) {
|
|
1513
|
+
candidate = file_join(paths[i], id + extensions[j]);
|
|
1514
|
+
|
|
1515
|
+
console.log(candidate);
|
|
1516
|
+
if (factories[candidate]) {
|
|
1517
|
+
return candidate;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
return null;
|
|
1523
|
+
};
|
|
1524
|
+
|
|
1525
|
+
/**
|
|
1526
|
+
Module contents
|
|
1527
|
+
*/
|
|
1528
|
+
Lp.module_contents = function(filename) {
|
|
1529
|
+
return this.factories[filename];
|
|
1530
|
+
};
|
|
1531
|
+
|
|
1532
|
+
/**
|
|
1533
|
+
Actually load the file with the given resolved filename. This filename has
|
|
1534
|
+
been checked, and is known to exist.
|
|
1535
|
+
*/
|
|
1536
|
+
function load_file(loader, filename) {
|
|
1537
|
+
var extension = load_extensions[PATH_RE.exec(filename)[3] || '.js'];
|
|
1538
|
+
|
|
1539
|
+
if (!extension) {
|
|
1540
|
+
throw new Error("Loader.load - Bad extension for resolved path");
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
extension(loader, filename);
|
|
1544
|
+
};
|
|
1545
|
+
|
|
1546
|
+
/**
|
|
1547
|
+
Run content, which by now must be javascript. If the content is a string,
|
|
1548
|
+
then it is simply evaluated. Within the browser it might be a function, so
|
|
1549
|
+
we call it, passing our standard args.
|
|
1550
|
+
|
|
1551
|
+
The arguments we pass are standardised as:
|
|
1552
|
+
|
|
1553
|
+
VM - Our opal vm variable which exposes runtime methods
|
|
1554
|
+
Qself - the top level ruby object, which is the 'self' for files
|
|
1555
|
+
filename - the Filename to run the file as for __FILE__
|
|
1556
|
+
|
|
1557
|
+
@param {String, Function} content The javascript content to be run.
|
|
1558
|
+
@param {String} filename Filename to run content as.
|
|
1559
|
+
*/
|
|
1560
|
+
function execute_file(loader, content, filename) {
|
|
1561
|
+
|
|
1562
|
+
var args = [Vm, Qself, filename];
|
|
1563
|
+
|
|
1564
|
+
if (typeof content === 'function') {
|
|
1565
|
+
return content.apply(Op, args);
|
|
1566
|
+
|
|
1567
|
+
} else if (typeof content === 'string') {
|
|
1568
|
+
var func = loader.wrap(content, filename);
|
|
1569
|
+
return func.apply(Op, args);
|
|
1570
|
+
|
|
1571
|
+
} else {
|
|
1572
|
+
throw new Error(
|
|
1573
|
+
"Loader.execute - bad content sent for '" + filename + "'");
|
|
1574
|
+
}
|
|
1575
|
+
};
|
|
1576
|
+
|
|
1577
|
+
// ..........................................................
|
|
1578
|
+
// FINAL INITILIZATION
|
|
1579
|
+
//
|
|
1580
|
+
|
|
1581
|
+
// init ruby runtime
|
|
1582
|
+
init();
|
|
1583
|
+
|
|
1584
|
+
// browser based loader - overriden by v8 context
|
|
1585
|
+
Op.loader = new Loader(Op);
|
|
1586
|
+
|
|
1587
|
+
// cache of filenames already evaluated
|
|
1588
|
+
Op.cache = {};
|
|
1589
|
+
|
|
1590
|
+
})();
|
|
1591
|
+
|
|
1592
|
+
// if in a commonjs system already (node etc), exports become our opal
|
|
1593
|
+
// object. Otherwise, in the browser, we just get a top level opal var
|
|
1594
|
+
if ((typeof require !== 'undefined') && (typeof module !== 'undefined')) {
|
|
1595
|
+
module.exports = opal;
|
|
1596
|
+
}
|
|
1597
|
+
|