|
| 1 | +use super::support::*; |
| 2 | + |
1 | 3 | use std::ffi::OsStr; |
2 | 4 | use std::process::Command; |
3 | 5 |
|
4 | 6 | use quickjs_oxide::{ |
5 | | - CallableRef, CompleteOrdinaryPropertyDescriptor, Context, JsString, ObjectRef, Runtime, |
6 | | - RuntimeError, Value, |
| 7 | + CompleteOrdinaryPropertyDescriptor, Context, JsString, ObjectRef, Runtime, RuntimeError, Value, |
7 | 8 | }; |
8 | 9 |
|
9 | 10 | // This target pins QuickJS 2026-06-04's `js_array_concat`, including |
@@ -534,84 +535,6 @@ fn array_concat_species_boxing_results_and_errors_use_pinned_realms() { |
534 | 535 | ); |
535 | 536 | } |
536 | 537 |
|
537 | | -fn compare_value_cases(group: &str, cases: &[(&str, &str)]) { |
538 | | - let Some(oracle) = std::env::var_os("QJS_ORACLE") else { |
539 | | - eprintln!("SKIP {group} differential: set QJS_ORACLE to upstream qjs"); |
540 | | - return; |
541 | | - }; |
542 | | - for &(description, source) in cases { |
543 | | - let expected = observe_oracle(&oracle, source, description); |
544 | | - let runtime = Runtime::new(); |
545 | | - let mut context = runtime.new_context(); |
546 | | - assert_eq!( |
547 | | - observe_rust_eval(&runtime, &mut context, source, description), |
548 | | - expected, |
549 | | - "{group} drifted for {description}: {source:?}", |
550 | | - ); |
551 | | - } |
552 | | -} |
553 | | - |
554 | | -fn observe_rust_eval( |
555 | | - runtime: &Runtime, |
556 | | - context: &mut Context, |
557 | | - source: &str, |
558 | | - description: &str, |
559 | | -) -> String { |
560 | | - match context.eval(source) { |
561 | | - Ok(value) => format!( |
562 | | - "return|{}|{}", |
563 | | - value_type(runtime, &value), |
564 | | - primitive_value_text(value), |
565 | | - ), |
566 | | - Err(RuntimeError::Exception) => { |
567 | | - let exception = context |
568 | | - .take_exception() |
569 | | - .unwrap_or_else(|error| panic!("take Rust exception for {description}: {error}")) |
570 | | - .unwrap_or_else(|| panic!("Rust exception was missing for {description}")); |
571 | | - match exception { |
572 | | - Value::Object(error) => format!( |
573 | | - "throw|object|{}|{}", |
574 | | - error_string_property(runtime, context, &error, "name", description), |
575 | | - error_string_property(runtime, context, &error, "message", description), |
576 | | - ), |
577 | | - value => format!( |
578 | | - "throw|{}|{}", |
579 | | - value_type(runtime, &value), |
580 | | - primitive_value_text(value), |
581 | | - ), |
582 | | - } |
583 | | - } |
584 | | - Err(error) => panic!("Rust engine failure for {description} ({source:?}): {error}"), |
585 | | - } |
586 | | -} |
587 | | - |
588 | | -fn observe_oracle(oracle: &OsStr, source: &str, description: &str) -> String { |
589 | | - let wrapper = r#" |
590 | | -try { |
591 | | - var value = std.evalScript(scriptArgs[0]); |
592 | | - print('return|' + typeof value + '|' + String(value)); |
593 | | -} catch (error) { |
594 | | - if (error !== null && typeof error === 'object') |
595 | | - print('throw|object|' + error.name + '|' + error.message); |
596 | | - else |
597 | | - print('throw|' + typeof error + '|' + String(error)); |
598 | | -} |
599 | | -"#; |
600 | | - let output = Command::new(oracle) |
601 | | - .args(["--std", "-e", wrapper, source]) |
602 | | - .output() |
603 | | - .unwrap_or_else(|error| panic!("could not run QuickJS for {description}: {error}")); |
604 | | - assert!( |
605 | | - output.status.success(), |
606 | | - "QuickJS observer failed for {description}: {}", |
607 | | - String::from_utf8_lossy(&output.stderr), |
608 | | - ); |
609 | | - String::from_utf8(output.stdout) |
610 | | - .unwrap_or_else(|error| panic!("QuickJS output was not UTF-8 for {description}: {error}")) |
611 | | - .trim_end() |
612 | | - .to_owned() |
613 | | -} |
614 | | - |
615 | 538 | fn rust_graph_observations() -> Vec<String> { |
616 | 539 | let runtime = Runtime::new(); |
617 | 540 | let mut context = runtime.new_context(); |
@@ -738,119 +661,3 @@ fn method_metadata( |
738 | 661 | runtime.is_constructor(callable.as_object()).unwrap(), |
739 | 662 | ) |
740 | 663 | } |
741 | | - |
742 | | -fn data_descriptor_bits(descriptor: &CompleteOrdinaryPropertyDescriptor) -> String { |
743 | | - let CompleteOrdinaryPropertyDescriptor::Data { |
744 | | - writable, |
745 | | - enumerable, |
746 | | - configurable, |
747 | | - .. |
748 | | - } = descriptor |
749 | | - else { |
750 | | - panic!("expected a data descriptor"); |
751 | | - }; |
752 | | - format!( |
753 | | - "D{}{}{}", |
754 | | - Number(*writable), |
755 | | - Number(*enumerable), |
756 | | - Number(*configurable), |
757 | | - ) |
758 | | -} |
759 | | - |
760 | | -fn property_callable( |
761 | | - runtime: &Runtime, |
762 | | - context: &mut Context, |
763 | | - object: &ObjectRef, |
764 | | - name: &str, |
765 | | -) -> CallableRef { |
766 | | - let key = runtime.intern_property_key(name).unwrap(); |
767 | | - let Value::Object(function) = context |
768 | | - .get_property(object, &key) |
769 | | - .unwrap_or_else(|error| panic!("read callable {name}: {error}")) |
770 | | - else { |
771 | | - panic!("{name} was not an object"); |
772 | | - }; |
773 | | - runtime |
774 | | - .as_callable(&function) |
775 | | - .unwrap() |
776 | | - .unwrap_or_else(|| panic!("{name} was not callable")) |
777 | | -} |
778 | | - |
779 | | -fn eval_object(context: &mut Context, source: &str, description: &str) -> ObjectRef { |
780 | | - let Value::Object(object) = context |
781 | | - .eval(source) |
782 | | - .unwrap_or_else(|error| panic!("Rust rejected {description} ({source:?}): {error}")) |
783 | | - else { |
784 | | - panic!("Rust {description} did not evaluate to an object"); |
785 | | - }; |
786 | | - object |
787 | | -} |
788 | | - |
789 | | -fn take_exception_object(context: &mut Context, description: &str) -> ObjectRef { |
790 | | - let Value::Object(error) = context |
791 | | - .take_exception() |
792 | | - .unwrap_or_else(|failure| panic!("take {description}: {failure}")) |
793 | | - .unwrap_or_else(|| panic!("{description} was missing")) |
794 | | - else { |
795 | | - panic!("{description} was not an object"); |
796 | | - }; |
797 | | - error |
798 | | -} |
799 | | - |
800 | | -fn error_string_property( |
801 | | - runtime: &Runtime, |
802 | | - context: &mut Context, |
803 | | - error: &ObjectRef, |
804 | | - name: &str, |
805 | | - description: &str, |
806 | | -) -> String { |
807 | | - let key = runtime.intern_property_key(name).unwrap(); |
808 | | - let Value::String(value) = context |
809 | | - .get_property(error, &key) |
810 | | - .unwrap_or_else(|failure| panic!("read Error.{name} for {description}: {failure}")) |
811 | | - else { |
812 | | - panic!("Error.{name} was not a string for {description}"); |
813 | | - }; |
814 | | - value.to_utf8_lossy() |
815 | | -} |
816 | | - |
817 | | -fn value_type(runtime: &Runtime, value: &Value) -> &'static str { |
818 | | - match value { |
819 | | - Value::Undefined => "undefined", |
820 | | - Value::Null => "object", |
821 | | - Value::Bool(_) => "boolean", |
822 | | - Value::Int(_) | Value::Float(_) => "number", |
823 | | - Value::BigInt(_) => "bigint", |
824 | | - Value::String(_) => "string", |
825 | | - Value::Object(object) => { |
826 | | - if runtime.as_callable(object).unwrap().is_some() { |
827 | | - "function" |
828 | | - } else { |
829 | | - "object" |
830 | | - } |
831 | | - } |
832 | | - Value::Symbol(_) => "symbol", |
833 | | - } |
834 | | -} |
835 | | - |
836 | | -fn primitive_value_text(value: Value) -> String { |
837 | | - match value { |
838 | | - Value::Undefined => "undefined".to_owned(), |
839 | | - Value::Null => "null".to_owned(), |
840 | | - Value::Bool(value) => value.to_string(), |
841 | | - Value::Int(value) => value.to_string(), |
842 | | - Value::Float(value) => quickjs_oxide::value::number_to_string(value), |
843 | | - Value::BigInt(value) => value.to_string(), |
844 | | - Value::String(value) => value.to_utf8_lossy(), |
845 | | - Value::Object(_) => "<object>".to_owned(), |
846 | | - Value::Symbol(_) => "<symbol>".to_owned(), |
847 | | - } |
848 | | -} |
849 | | - |
850 | | -struct Number(bool); |
851 | | - |
852 | | -impl std::fmt::Display for Number { |
853 | | - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
854 | | - formatter.write_str(if self.0 { "1" } else { "0" }) |
855 | | - } |
856 | | -} |
0 commit comments